^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/arch/arm/kernel/ecard.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 1995-2001 Russell King
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Find all installed expansion cards, and handle interrupts from them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Created from information from Acorns RiscOS3 PRMs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * 08-Dec-1996 RMK Added code for the 9'th expansion card - the ether
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * podule slot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * 06-May-1997 RMK Added blacklist for cards whose loader doesn't work.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * 12-Sep-1997 RMK Created new handling of interrupt enables/disables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * - cards can now register their own routine to control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * interrupts (recommended).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * 29-Sep-1997 RMK Expansion card interrupt hardware not being re-enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * on reset from Linux. (Caused cards not to respond
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * under RiscOS without hard reset).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * 15-Feb-1998 RMK Added DMA support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * 12-Sep-1998 RMK Added EASI support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * 10-Jan-1999 RMK Run loaders in a simulated RISC OS environment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * 17-Apr-1999 RMK Support for EASI Type C cycles.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define ECARD_C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/sched/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/kthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <asm/dma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <asm/ecard.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <mach/hardware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <asm/mmu_context.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <asm/mach/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <asm/tlbflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include "ecard.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct ecard_request {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) void (*fn)(struct ecard_request *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ecard_t *ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned int address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned int length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned int use_loader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) void *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct completion *complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct expcard_quirklist {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned short manufacturer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned short product;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) const char *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) void (*init)(ecard_t *ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static ecard_t *cards;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static ecard_t *slot_to_expcard[MAX_ECARDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static unsigned int ectcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static void atomwide_3p_quirk(ecard_t *ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* List of descriptions of cards which don't have an extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * identification, or chunk directories containing a description.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static struct expcard_quirklist quirklist[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, NULL, atomwide_3p_quirk },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) asmlinkage extern int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ecard_loader_reset(unsigned long base, loader_t loader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) asmlinkage extern int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ecard_loader_read(int off, unsigned long base, loader_t loader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static inline unsigned short ecard_getu16(unsigned char *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return v[0] | v[1] << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static inline signed long ecard_gets24(unsigned char *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static inline ecard_t *slot_to_ecard(unsigned int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return slot < MAX_ECARDS ? slot_to_expcard[slot] : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* ===================== Expansion card daemon ======================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * Since the loader programs on the expansion cards need to be run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * in a specific environment, create a separate task with this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * environment up, and pass requests to this task as and when we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * need to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * This should allow 99% of loaders to be called from Linux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * From a security standpoint, we trust the card vendors. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * may be a misplaced trust.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static void ecard_task_reset(struct ecard_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct expansion_card *ec = req->ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) res = ec->slot_no == 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ? &ec->resource[ECARD_RES_MEMC]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) : ec->easi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ? &ec->resource[ECARD_RES_EASI]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) : &ec->resource[ECARD_RES_IOCSYNC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ecard_loader_reset(res->start, ec->loader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void ecard_task_readbytes(struct ecard_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct expansion_card *ec = req->ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) unsigned char *buf = req->buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) unsigned int len = req->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) unsigned int off = req->address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (ec->slot_no == 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) void __iomem *base = (void __iomem *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ec->resource[ECARD_RES_MEMC].start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * The card maintains an index which increments the address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * into a 4096-byte page on each access. We need to keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * track of the counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static unsigned int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned int page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) page = (off >> 12) * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (page > 256 * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) off &= 4095;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * If we are reading offset 0, or our current index is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * greater than the offset, reset the hardware index counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (off == 0 || index > off) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) writeb(0, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * Increment the hardware index counter until we get to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * required offset. The read bytes are discarded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) while (index < off) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) readb(base + page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) index += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) while (len--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) *buf++ = readb(base + page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) index += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) unsigned long base = (ec->easi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) ? &ec->resource[ECARD_RES_EASI]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) : &ec->resource[ECARD_RES_IOCSYNC])->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) void __iomem *pbase = (void __iomem *)base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (!req->use_loader || !ec->loader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) off *= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) while (len--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) *buf++ = readb(pbase + off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) off += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) while(len--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * The following is required by some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * expansion card loader programs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) *(unsigned long *)0x108 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) *buf++ = ecard_loader_read(off++, base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ec->loader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static DECLARE_WAIT_QUEUE_HEAD(ecard_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static struct ecard_request *ecard_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static DEFINE_MUTEX(ecard_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * Set up the expansion card daemon's page tables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static void ecard_init_pgtables(struct mm_struct *mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct vm_area_struct vma = TLB_FLUSH_VMA(mm, VM_EXEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /* We want to set up the page tables for the following mapping:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * Virtual Physical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * 0x03000000 0x03000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * 0x03010000 unmapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * 0x03210000 0x03210000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * 0x03400000 unmapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * 0x08000000 0x08000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * 0x10000000 unmapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * FIXME: we don't follow this 100% yet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) pgd_t *src_pgd, *dst_pgd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) src_pgd = pgd_offset(mm, (unsigned long)IO_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) dst_pgd = pgd_offset(mm, IO_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) src_pgd = pgd_offset(mm, (unsigned long)EASI_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) dst_pgd = pgd_offset(mm, EASI_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (EASI_SIZE / PGDIR_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) flush_tlb_range(&vma, IO_START, IO_START + IO_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) flush_tlb_range(&vma, EASI_START, EASI_START + EASI_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static int ecard_init_mm(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct mm_struct * mm = mm_alloc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct mm_struct *active_mm = current->active_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (!mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) current->mm = mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) current->active_mm = mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) activate_mm(active_mm, mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) mmdrop(active_mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ecard_init_pgtables(mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ecard_task(void * unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * Allocate a mm. We're not a lazy-TLB kernel task since we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * to set page table entries where the user space would be. Note
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * that this also creates the page tables. Failure is not an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * option here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (ecard_init_mm())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) panic("kecardd: unable to alloc mm\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct ecard_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) wait_event_interruptible(ecard_wait, ecard_req != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) req = xchg(&ecard_req, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (req != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) req->fn(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) complete(req->complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * Wake the expansion card daemon to action our request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * FIXME: The test here is not sufficient to detect if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * kcardd is running.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static void ecard_call(struct ecard_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) DECLARE_COMPLETION_ONSTACK(completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) req->complete = &completion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) mutex_lock(&ecard_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ecard_req = req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) wake_up(&ecard_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * Now wait for kecardd to run.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) wait_for_completion(&completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) mutex_unlock(&ecard_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /* ======================= Mid-level card control ===================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct ecard_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) req.fn = ecard_task_readbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) req.ec = ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) req.address = off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) req.length = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) req.use_loader = useld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) req.buffer = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) ecard_call(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct ex_chunk_dir excd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) int index = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) int useld = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (!ec->cid.cd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) while(1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ecard_readbytes(&excd, ec, index, 8, useld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) index += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (c_id(&excd) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (!useld && ec->loader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) useld = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (c_id(&excd) == 0xf0) { /* link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) index = c_start(&excd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (c_id(&excd) == 0x80) { /* loader */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (!ec->loader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) ec->loader = kmalloc(c_len(&excd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (ec->loader)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ecard_readbytes(ec->loader, ec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) (int)c_start(&excd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) c_len(&excd), useld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (c_id(&excd) == id && num-- == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (c_id(&excd) & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) switch (c_id(&excd) & 0x70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) case 0x70:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) ecard_readbytes((unsigned char *)excd.d.string, ec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) (int)c_start(&excd), c_len(&excd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) useld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) case 0x00:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) cd->start_offset = c_start(&excd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) memcpy(cd->d.string, excd.d.string, 256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /* ======================= Interrupt control ============================ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static void ecard_def_irq_enable(ecard_t *ec, int irqnr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static void ecard_def_irq_disable(ecard_t *ec, int irqnr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static int ecard_def_irq_pending(ecard_t *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return !ec->irqmask || readb(ec->irqaddr) & ec->irqmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) panic("ecard_def_fiq_enable called - impossible");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static void ecard_def_fiq_disable(ecard_t *ec, int fiqnr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) panic("ecard_def_fiq_disable called - impossible");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static int ecard_def_fiq_pending(ecard_t *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return !ec->fiqmask || readb(ec->fiqaddr) & ec->fiqmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) static expansioncard_ops_t ecard_default_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ecard_def_irq_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) ecard_def_irq_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) ecard_def_irq_pending,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ecard_def_fiq_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ecard_def_fiq_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) ecard_def_fiq_pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * Enable and disable interrupts from expansion cards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * (interrupts are disabled for these functions).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * They are not meant to be called directly, but via enable/disable_irq.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static void ecard_irq_unmask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) ecard_t *ec = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (ec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (!ec->ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) ec->ops = &ecard_default_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (ec->claimed && ec->ops->irqenable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ec->ops->irqenable(ec, d->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) printk(KERN_ERR "ecard: rejecting request to "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) "enable IRQs for %d\n", d->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static void ecard_irq_mask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ecard_t *ec = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (ec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (!ec->ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ec->ops = &ecard_default_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (ec->ops && ec->ops->irqdisable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ec->ops->irqdisable(ec, d->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) static struct irq_chip ecard_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) .name = "ECARD",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) .irq_ack = ecard_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) .irq_mask = ecard_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) .irq_unmask = ecard_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) void ecard_enablefiq(unsigned int fiqnr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) ecard_t *ec = slot_to_ecard(fiqnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (ec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (!ec->ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ec->ops = &ecard_default_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (ec->claimed && ec->ops->fiqenable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) ec->ops->fiqenable(ec, fiqnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) printk(KERN_ERR "ecard: rejecting request to "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) "enable FIQs for %d\n", fiqnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) void ecard_disablefiq(unsigned int fiqnr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) ecard_t *ec = slot_to_ecard(fiqnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (ec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (!ec->ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) ec->ops = &ecard_default_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (ec->ops->fiqdisable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) ec->ops->fiqdisable(ec, fiqnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static void ecard_dump_irq_state(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ecard_t *ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) printk("Expansion card IRQ state:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) for (ec = cards; ec; ec = ec->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) const char *claimed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (ec->slot_no == 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) claimed = ec->claimed ? "" : "not ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (ec->ops && ec->ops->irqpending &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ec->ops != &ecard_default_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) printk(" %d: %sclaimed irq %spending\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ec->slot_no, claimed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) ec->ops->irqpending(ec) ? "" : "not ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) printk(" %d: %sclaimed irqaddr %p, mask = %02X, status = %02X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) ec->slot_no, claimed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) ec->irqaddr, ec->irqmask, readb(ec->irqaddr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static void ecard_check_lockup(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static unsigned long last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) static int lockup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * If the timer interrupt has not run since the last million
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * unrecognised expansion card interrupts, then there is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * something seriously wrong. Disable the expansion card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) * interrupts so at least we can continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * Maybe we ought to start a timer to re-enable them some time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * later?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (last == jiffies) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) lockup += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (lockup > 1000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) printk(KERN_ERR "\nInterrupt lockup detected - "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) "disabling all expansion card interrupts\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) desc->irq_data.chip->irq_mask(&desc->irq_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) ecard_dump_irq_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) lockup = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * If we did not recognise the source of this interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * warn the user, but don't flood the user with these messages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (!last || time_after(jiffies, last + 5*HZ)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) last = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) printk(KERN_WARNING "Unrecognised interrupt from backplane\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ecard_dump_irq_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static void ecard_irq_handler(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) ecard_t *ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) int called = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) desc->irq_data.chip->irq_mask(&desc->irq_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) for (ec = cards; ec; ec = ec->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) int pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (!ec->claimed || !ec->irq || ec->slot_no == 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (ec->ops && ec->ops->irqpending)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) pending = ec->ops->irqpending(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) pending = ecard_default_ops.irqpending(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (pending) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) generic_handle_irq(ec->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) called ++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) desc->irq_data.chip->irq_unmask(&desc->irq_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (called == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) ecard_check_lockup(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static void __iomem *__ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) void __iomem *address = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) int slot = ec->slot_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (ec->slot_no == 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return ECARD_MEMC8_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) ectcr &= ~(1 << slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) case ECARD_MEMC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (slot < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) address = ECARD_MEMC_BASE + (slot << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) case ECARD_IOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (slot < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) address = ECARD_IOC_BASE + (slot << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) address = ECARD_IOC4_BASE + ((slot - 4) << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) address += speed << 19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) case ECARD_EASI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) address = ECARD_EASI_BASE + (slot << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (speed == ECARD_FAST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ectcr |= 1 << slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) #ifdef IOMD_ECTCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) iomd_writeb(ectcr, IOMD_ECTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static int ecard_prints(struct seq_file *m, ecard_t *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) seq_printf(m, " %d: %s ", ec->slot_no, ec->easi ? "EASI" : " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (ec->cid.id == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) struct in_chunk_dir incd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) seq_printf(m, "[%04X:%04X] ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ec->cid.manufacturer, ec->cid.product);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (!ec->card_desc && ec->cid.cd &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) ecard_readchunk(&incd, ec, 0xf5, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ec->card_desc = kmalloc(strlen(incd.d.string)+1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (ec->card_desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) strcpy((char *)ec->card_desc, incd.d.string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) seq_printf(m, "%s\n", ec->card_desc ? ec->card_desc : "*unknown*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) seq_printf(m, "Simple card %d\n", ec->cid.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static int ecard_devices_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) ecard_t *ec = cards;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) while (ec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ecard_prints(m, ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) ec = ec->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static struct proc_dir_entry *proc_bus_ecard_dir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static void ecard_proc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) proc_bus_ecard_dir = proc_mkdir("bus/ecard", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) proc_create_single("devices", 0, proc_bus_ecard_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) ecard_devices_proc_show);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) #define ec_set_resource(ec,nr,st,sz) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) (ec)->resource[nr].name = dev_name(&ec->dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) (ec)->resource[nr].start = st; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) (ec)->resource[nr].end = (st) + (sz) - 1; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) (ec)->resource[nr].flags = IORESOURCE_MEM; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) static void __init ecard_free_card(struct expansion_card *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) for (i = 0; i < ECARD_NUM_RESOURCES; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (ec->resource[i].flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) release_resource(&ec->resource[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) kfree(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) static struct expansion_card *__init ecard_alloc_card(int type, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) struct expansion_card *ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) unsigned long base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) ec = kzalloc(sizeof(ecard_t), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (!ec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) ec = ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) goto nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ec->slot_no = slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) ec->easi = type == ECARD_EASI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) ec->irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) ec->fiq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) ec->dma = NO_DMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) ec->ops = &ecard_default_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) dev_set_name(&ec->dev, "ecard%d", slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ec->dev.parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) ec->dev.bus = &ecard_bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) ec->dev.dma_mask = &ec->dma_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) ec->dma_mask = (u64)0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) ec->dev.coherent_dma_mask = ec->dma_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (slot < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) ec_set_resource(ec, ECARD_RES_MEMC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) PODSLOT_MEMC_BASE + (slot << 14),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) PODSLOT_MEMC_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) base = PODSLOT_IOC0_BASE + (slot << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) base = PODSLOT_IOC4_BASE + ((slot - 4) << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) #ifdef CONFIG_ARCH_RPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (slot < 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) ec_set_resource(ec, ECARD_RES_EASI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) PODSLOT_EASI_BASE + (slot << 24),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) PODSLOT_EASI_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (slot == 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE, NETSLOT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) for (i = 0; i <= ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) ec_set_resource(ec, i + ECARD_RES_IOCSLOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) base + (i << 19), PODSLOT_IOC_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) for (i = 0; i < ECARD_NUM_RESOURCES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (ec->resource[i].flags &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) request_resource(&iomem_resource, &ec->resource[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) dev_err(&ec->dev, "resource(s) not available\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) ec->resource[i].end -= ec->resource[i].start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) ec->resource[i].start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) ec->resource[i].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) nomem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) return ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) static ssize_t irq_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) struct expansion_card *ec = ECARD_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return sprintf(buf, "%u\n", ec->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) static DEVICE_ATTR_RO(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) static ssize_t dma_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct expansion_card *ec = ECARD_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return sprintf(buf, "%u\n", ec->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static DEVICE_ATTR_RO(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) static ssize_t resource_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) struct expansion_card *ec = ECARD_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) char *str = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) for (i = 0; i < ECARD_NUM_RESOURCES; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) str += sprintf(str, "%08x %08x %08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) ec->resource[i].start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) ec->resource[i].end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) ec->resource[i].flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return str - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static DEVICE_ATTR_RO(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static ssize_t vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) struct expansion_card *ec = ECARD_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return sprintf(buf, "%u\n", ec->cid.manufacturer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) static DEVICE_ATTR_RO(vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) static ssize_t device_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) struct expansion_card *ec = ECARD_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return sprintf(buf, "%u\n", ec->cid.product);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) static DEVICE_ATTR_RO(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static ssize_t type_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct expansion_card *ec = ECARD_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return sprintf(buf, "%s\n", ec->easi ? "EASI" : "IOC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) static DEVICE_ATTR_RO(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) static struct attribute *ecard_dev_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) &dev_attr_device.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) &dev_attr_dma.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) &dev_attr_irq.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) &dev_attr_resource.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) &dev_attr_type.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) &dev_attr_vendor.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) ATTRIBUTE_GROUPS(ecard_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) int ecard_request_resources(struct expansion_card *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) int i, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) for (i = 0; i < ECARD_NUM_RESOURCES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if (ecard_resource_end(ec, i) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) !request_mem_region(ecard_resource_start(ec, i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) ecard_resource_len(ec, i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) ec->dev.driver->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) while (i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (ecard_resource_end(ec, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) release_mem_region(ecard_resource_start(ec, i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) ecard_resource_len(ec, i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) EXPORT_SYMBOL(ecard_request_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) void ecard_release_resources(struct expansion_card *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) for (i = 0; i < ECARD_NUM_RESOURCES; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (ecard_resource_end(ec, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) release_mem_region(ecard_resource_start(ec, i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) ecard_resource_len(ec, i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) EXPORT_SYMBOL(ecard_release_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) void ecard_setirq(struct expansion_card *ec, const struct expansion_card_ops *ops, void *irq_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) ec->irq_data = irq_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) ec->ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) EXPORT_SYMBOL(ecard_setirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) void __iomem *ecardm_iomap(struct expansion_card *ec, unsigned int res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) unsigned long offset, unsigned long maxsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) unsigned long start = ecard_resource_start(ec, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) unsigned long end = ecard_resource_end(ec, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (offset > (end - start))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) start += offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (maxsize && end - start > maxsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) end = start + maxsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return devm_ioremap(&ec->dev, start, end - start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) EXPORT_SYMBOL(ecardm_iomap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) static void atomwide_3p_quirk(ecard_t *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) void __iomem *addr = __ecard_address(ec, ECARD_IOC, ECARD_SYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) /* Disable interrupts on each port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) for (i = 0x2000; i <= 0x2800; i += 0x0400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) writeb(0, addr + i + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) * Probe for an expansion card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * If bit 1 of the first byte of the card is set, then the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) * card does not exist.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static int __init ecard_probe(int slot, unsigned irq, card_type_t type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) ecard_t **ecp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) ecard_t *ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) struct ex_ecid cid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) void __iomem *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) int i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) ec = ecard_alloc_card(type, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (IS_ERR(ec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) rc = PTR_ERR(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) goto nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if ((addr = __ecard_address(ec, type, ECARD_SYNC)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) goto nodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) cid.r_zero = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) ecard_readbytes(&cid, ec, 0, 16, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (cid.r_zero)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) goto nodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) ec->cid.id = cid.r_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) ec->cid.cd = cid.r_cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) ec->cid.is = cid.r_is;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) ec->cid.w = cid.r_w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) ec->cid.manufacturer = ecard_getu16(cid.r_manu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) ec->cid.product = ecard_getu16(cid.r_prod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) ec->cid.country = cid.r_country;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) ec->cid.irqmask = cid.r_irqmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) ec->cid.irqoff = ecard_gets24(cid.r_irqoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) ec->cid.fiqmask = cid.r_fiqmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) ec->fiqaddr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) ec->irqaddr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (ec->cid.is) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) ec->irqmask = ec->cid.irqmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) ec->irqaddr += ec->cid.irqoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) ec->fiqmask = ec->cid.fiqmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) ec->fiqaddr += ec->cid.fiqoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) ec->irqmask = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) ec->fiqmask = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) for (i = 0; i < ARRAY_SIZE(quirklist); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (quirklist[i].manufacturer == ec->cid.manufacturer &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) quirklist[i].product == ec->cid.product) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (quirklist[i].type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) ec->card_desc = quirklist[i].type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (quirklist[i].init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) quirklist[i].init(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) ec->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) * hook the interrupt handlers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) if (slot < 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) irq_set_chip_and_handler(ec->irq, &ecard_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) irq_set_chip_data(ec->irq, ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) irq_clear_status_flags(ec->irq, IRQ_NOREQUEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) #ifdef CONFIG_ARCH_RPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) /* On RiscPC, only first two slots have DMA capability */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (slot < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) ec->dma = 2 + slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) for (ecp = &cards; *ecp; ecp = &(*ecp)->next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) *ecp = ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) slot_to_expcard[slot] = ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) rc = device_register(&ec->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) goto nodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) nodev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) ecard_free_card(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) nomem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) * Initialise the expansion card system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) * Locate all hardware - interrupt management and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) * actual cards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) static int __init ecard_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct task_struct *task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) int slot, irqbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) irqbase = irq_alloc_descs(-1, 0, 8, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (irqbase < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return irqbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) task = kthread_run(ecard_task, NULL, "kecardd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (IS_ERR(task)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) printk(KERN_ERR "Ecard: unable to create kernel thread: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) PTR_ERR(task));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) irq_free_descs(irqbase, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) return PTR_ERR(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) printk("Probing expansion cards\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) for (slot = 0; slot < 8; slot ++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (ecard_probe(slot, irqbase + slot, ECARD_EASI) == -ENODEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) ecard_probe(slot, irqbase + slot, ECARD_IOC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) ecard_probe(8, 11, ECARD_IOC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) irq_set_chained_handler(IRQ_EXPANSIONCARD, ecard_irq_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) ecard_proc_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) subsys_initcall(ecard_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * ECARD "bus"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) static const struct ecard_id *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) for (i = 0; ids[i].manufacturer != 65535; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (ec->cid.manufacturer == ids[i].manufacturer &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) ec->cid.product == ids[i].product)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) return ids + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static int ecard_drv_probe(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) struct expansion_card *ec = ECARD_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) struct ecard_driver *drv = ECARD_DRV(dev->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) const struct ecard_id *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) id = ecard_match_device(drv->id_table, ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) ec->claimed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) ret = drv->probe(ec, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) ec->claimed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) static int ecard_drv_remove(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) struct expansion_card *ec = ECARD_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) struct ecard_driver *drv = ECARD_DRV(dev->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) drv->remove(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) ec->claimed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * Restore the default operations. We ensure that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) * ops are set before we change the data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) ec->ops = &ecard_default_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) ec->irq_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) * Before rebooting, we must make sure that the expansion card is in a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) * sensible state, so it can be re-detected. This means that the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) * page of the ROM must be visible. We call the expansion cards reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) * handler, if any.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static void ecard_drv_shutdown(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) struct expansion_card *ec = ECARD_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) struct ecard_driver *drv = ECARD_DRV(dev->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct ecard_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (dev->driver) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (drv->shutdown)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) drv->shutdown(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) ec->claimed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) * If this card has a loader, call the reset handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) if (ec->loader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) req.fn = ecard_task_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) req.ec = ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) ecard_call(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) int ecard_register_driver(struct ecard_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) drv->drv.bus = &ecard_bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return driver_register(&drv->drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) void ecard_remove_driver(struct ecard_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) driver_unregister(&drv->drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) static int ecard_match(struct device *_dev, struct device_driver *_drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) struct expansion_card *ec = ECARD_DEV(_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) struct ecard_driver *drv = ECARD_DRV(_drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (drv->id_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) ret = ecard_match_device(drv->id_table, ec) != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) ret = ec->cid.id == drv->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) struct bus_type ecard_bus_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) .name = "ecard",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) .dev_groups = ecard_dev_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) .match = ecard_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) .probe = ecard_drv_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) .remove = ecard_drv_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) .shutdown = ecard_drv_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) static int ecard_bus_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) return bus_register(&ecard_bus_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) postcore_initcall(ecard_bus_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) EXPORT_SYMBOL(ecard_readchunk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) EXPORT_SYMBOL(ecard_register_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) EXPORT_SYMBOL(ecard_remove_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) EXPORT_SYMBOL(ecard_bus_type);