| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * linux/arch/arm/kernel/ecard.c |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright 1995-2001 Russell King |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 7 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 8 | | - * published by the Free Software Foundation. |
|---|
| 9 | 6 | * |
|---|
| 10 | 7 | * Find all installed expansion cards, and handle interrupts from them. |
|---|
| 11 | 8 | * |
|---|
| .. | .. |
|---|
| 66 | 63 | struct completion *complete; |
|---|
| 67 | 64 | }; |
|---|
| 68 | 65 | |
|---|
| 69 | | -struct expcard_blacklist { |
|---|
| 66 | +struct expcard_quirklist { |
|---|
| 70 | 67 | unsigned short manufacturer; |
|---|
| 71 | 68 | unsigned short product; |
|---|
| 72 | 69 | const char *type; |
|---|
| 70 | + void (*init)(ecard_t *ec); |
|---|
| 73 | 71 | }; |
|---|
| 74 | 72 | |
|---|
| 75 | 73 | static ecard_t *cards; |
|---|
| 76 | 74 | static ecard_t *slot_to_expcard[MAX_ECARDS]; |
|---|
| 77 | 75 | static unsigned int ectcr; |
|---|
| 78 | 76 | |
|---|
| 77 | +static void atomwide_3p_quirk(ecard_t *ec); |
|---|
| 78 | + |
|---|
| 79 | 79 | /* List of descriptions of cards which don't have an extended |
|---|
| 80 | 80 | * identification, or chunk directories containing a description. |
|---|
| 81 | 81 | */ |
|---|
| 82 | | -static struct expcard_blacklist __initdata blacklist[] = { |
|---|
| 83 | | - { MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" } |
|---|
| 82 | +static struct expcard_quirklist quirklist[] __initdata = { |
|---|
| 83 | + { MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" }, |
|---|
| 84 | + { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, NULL, atomwide_3p_quirk }, |
|---|
| 84 | 85 | }; |
|---|
| 85 | 86 | |
|---|
| 86 | 87 | asmlinkage extern int |
|---|
| .. | .. |
|---|
| 496 | 497 | printk("Expansion card IRQ state:\n"); |
|---|
| 497 | 498 | |
|---|
| 498 | 499 | for (ec = cards; ec; ec = ec->next) { |
|---|
| 500 | + const char *claimed; |
|---|
| 501 | + |
|---|
| 499 | 502 | if (ec->slot_no == 8) |
|---|
| 500 | 503 | continue; |
|---|
| 501 | 504 | |
|---|
| 502 | | - printk(" %d: %sclaimed, ", |
|---|
| 503 | | - ec->slot_no, ec->claimed ? "" : "not "); |
|---|
| 505 | + claimed = ec->claimed ? "" : "not "; |
|---|
| 504 | 506 | |
|---|
| 505 | 507 | if (ec->ops && ec->ops->irqpending && |
|---|
| 506 | 508 | ec->ops != &ecard_default_ops) |
|---|
| 507 | | - printk("irq %spending\n", |
|---|
| 509 | + printk(" %d: %sclaimed irq %spending\n", |
|---|
| 510 | + ec->slot_no, claimed, |
|---|
| 508 | 511 | ec->ops->irqpending(ec) ? "" : "not "); |
|---|
| 509 | 512 | else |
|---|
| 510 | | - printk("irqaddr %p, mask = %02X, status = %02X\n", |
|---|
| 513 | + printk(" %d: %sclaimed irqaddr %p, mask = %02X, status = %02X\n", |
|---|
| 514 | + ec->slot_no, claimed, |
|---|
| 511 | 515 | ec->irqaddr, ec->irqmask, readb(ec->irqaddr)); |
|---|
| 512 | 516 | } |
|---|
| 513 | 517 | } |
|---|
| .. | .. |
|---|
| 868 | 872 | } |
|---|
| 869 | 873 | EXPORT_SYMBOL(ecardm_iomap); |
|---|
| 870 | 874 | |
|---|
| 875 | +static void atomwide_3p_quirk(ecard_t *ec) |
|---|
| 876 | +{ |
|---|
| 877 | + void __iomem *addr = __ecard_address(ec, ECARD_IOC, ECARD_SYNC); |
|---|
| 878 | + unsigned int i; |
|---|
| 879 | + |
|---|
| 880 | + /* Disable interrupts on each port */ |
|---|
| 881 | + for (i = 0x2000; i <= 0x2800; i += 0x0400) |
|---|
| 882 | + writeb(0, addr + i + 4); |
|---|
| 883 | +} |
|---|
| 884 | + |
|---|
| 871 | 885 | /* |
|---|
| 872 | 886 | * Probe for an expansion card. |
|---|
| 873 | 887 | * |
|---|
| .. | .. |
|---|
| 921 | 935 | ec->fiqmask = 4; |
|---|
| 922 | 936 | } |
|---|
| 923 | 937 | |
|---|
| 924 | | - for (i = 0; i < ARRAY_SIZE(blacklist); i++) |
|---|
| 925 | | - if (blacklist[i].manufacturer == ec->cid.manufacturer && |
|---|
| 926 | | - blacklist[i].product == ec->cid.product) { |
|---|
| 927 | | - ec->card_desc = blacklist[i].type; |
|---|
| 938 | + for (i = 0; i < ARRAY_SIZE(quirklist); i++) |
|---|
| 939 | + if (quirklist[i].manufacturer == ec->cid.manufacturer && |
|---|
| 940 | + quirklist[i].product == ec->cid.product) { |
|---|
| 941 | + if (quirklist[i].type) |
|---|
| 942 | + ec->card_desc = quirklist[i].type; |
|---|
| 943 | + if (quirklist[i].init) |
|---|
| 944 | + quirklist[i].init(ec); |
|---|
| 928 | 945 | break; |
|---|
| 929 | 946 | } |
|---|
| 930 | 947 | |
|---|