1*09c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 266213b3cSManuel Lauss /* 366213b3cSManuel Lauss * PCMCIA socket code for the Alchemy Db1xxx/Pb1xxx boards. 466213b3cSManuel Lauss * 566213b3cSManuel Lauss * Copyright (c) 2009 Manuel Lauss <manuel.lauss@gmail.com> 666213b3cSManuel Lauss * 766213b3cSManuel Lauss */ 866213b3cSManuel Lauss 966213b3cSManuel Lauss /* This is a fairly generic PCMCIA socket driver suitable for the 1066213b3cSManuel Lauss * following Alchemy Development boards: 1164cd04d0SManuel Lauss * Db1000, Db/Pb1500, Db/Pb1100, Db/Pb1550, Db/Pb1200, Db1300 1266213b3cSManuel Lauss * 1366213b3cSManuel Lauss * The Db1000 is used as a reference: Per-socket card-, carddetect- and 1466213b3cSManuel Lauss * statuschange IRQs connected to SoC GPIOs, control and status register 1566213b3cSManuel Lauss * bits arranged in per-socket groups in an external PLD. All boards 1666213b3cSManuel Lauss * listed here use this layout, including bit positions and meanings. 1766213b3cSManuel Lauss * Of course there are exceptions in later boards: 1866213b3cSManuel Lauss * 1966213b3cSManuel Lauss * - Pb1100/Pb1500: single socket only; voltage key bits VS are 2066213b3cSManuel Lauss * at STATUS[5:4] (instead of STATUS[1:0]). 2166213b3cSManuel Lauss * - Au1200-based: additional card-eject irqs, irqs not gpios! 2264cd04d0SManuel Lauss * - Db1300: Db1200-like, no pwr ctrl, single socket (#1). 2366213b3cSManuel Lauss */ 2466213b3cSManuel Lauss 2566213b3cSManuel Lauss #include <linux/delay.h> 2666213b3cSManuel Lauss #include <linux/gpio.h> 2766213b3cSManuel Lauss #include <linux/interrupt.h> 2866213b3cSManuel Lauss #include <linux/pm.h> 293bf8d64dSPaul Gortmaker #include <linux/module.h> 3066213b3cSManuel Lauss #include <linux/platform_device.h> 3166213b3cSManuel Lauss #include <linux/resource.h> 325a0e3ad6STejun Heo #include <linux/slab.h> 3366213b3cSManuel Lauss #include <linux/spinlock.h> 3466213b3cSManuel Lauss 3566213b3cSManuel Lauss #include <pcmcia/ss.h> 3666213b3cSManuel Lauss 3766213b3cSManuel Lauss #include <asm/mach-au1x00/au1000.h> 3866213b3cSManuel Lauss #include <asm/mach-db1x00/bcsr.h> 3966213b3cSManuel Lauss 4066213b3cSManuel Lauss #define MEM_MAP_SIZE 0x400000 4166213b3cSManuel Lauss #define IO_MAP_SIZE 0x1000 4266213b3cSManuel Lauss 4366213b3cSManuel Lauss struct db1x_pcmcia_sock { 4466213b3cSManuel Lauss struct pcmcia_socket socket; 4566213b3cSManuel Lauss int nr; /* socket number */ 4666213b3cSManuel Lauss void *virt_io; 4766213b3cSManuel Lauss 4811b897cfSManuel Lauss phys_addr_t phys_io; 4911b897cfSManuel Lauss phys_addr_t phys_attr; 5011b897cfSManuel Lauss phys_addr_t phys_mem; 5166213b3cSManuel Lauss 5266213b3cSManuel Lauss /* previous flags for set_socket() */ 5366213b3cSManuel Lauss unsigned int old_flags; 5466213b3cSManuel Lauss 5566213b3cSManuel Lauss /* interrupt sources: linux irq numbers! */ 5666213b3cSManuel Lauss int insert_irq; /* default carddetect irq */ 5766213b3cSManuel Lauss int stschg_irq; /* card-status-change irq */ 5866213b3cSManuel Lauss int card_irq; /* card irq */ 5966213b3cSManuel Lauss int eject_irq; /* db1200/pb1200 have these */ 60e34b6fcfSManuel Lauss int insert_gpio; /* db1000 carddetect gpio */ 6166213b3cSManuel Lauss 6266213b3cSManuel Lauss #define BOARD_TYPE_DEFAULT 0 /* most boards */ 6366213b3cSManuel Lauss #define BOARD_TYPE_DB1200 1 /* IRQs aren't gpios */ 6466213b3cSManuel Lauss #define BOARD_TYPE_PB1100 2 /* VS bits slightly different */ 6564cd04d0SManuel Lauss #define BOARD_TYPE_DB1300 3 /* no power control */ 6666213b3cSManuel Lauss int board_type; 6766213b3cSManuel Lauss }; 6866213b3cSManuel Lauss 6966213b3cSManuel Lauss #define to_db1x_socket(x) container_of(x, struct db1x_pcmcia_sock, socket) 7066213b3cSManuel Lauss 7164cd04d0SManuel Lauss static int db1300_card_inserted(struct db1x_pcmcia_sock *sock) 7264cd04d0SManuel Lauss { 7364cd04d0SManuel Lauss return bcsr_read(BCSR_SIGSTAT) & (1 << 8); 7464cd04d0SManuel Lauss } 7564cd04d0SManuel Lauss 7666213b3cSManuel Lauss /* DB/PB1200: check CPLD SIGSTATUS register bit 10/12 */ 7766213b3cSManuel Lauss static int db1200_card_inserted(struct db1x_pcmcia_sock *sock) 7866213b3cSManuel Lauss { 7966213b3cSManuel Lauss unsigned short sigstat; 8066213b3cSManuel Lauss 8166213b3cSManuel Lauss sigstat = bcsr_read(BCSR_SIGSTAT); 8266213b3cSManuel Lauss return sigstat & 1 << (8 + 2 * sock->nr); 8366213b3cSManuel Lauss } 8466213b3cSManuel Lauss 8566213b3cSManuel Lauss /* carddetect gpio: low-active */ 8666213b3cSManuel Lauss static int db1000_card_inserted(struct db1x_pcmcia_sock *sock) 8766213b3cSManuel Lauss { 88e34b6fcfSManuel Lauss return !gpio_get_value(sock->insert_gpio); 8966213b3cSManuel Lauss } 9066213b3cSManuel Lauss 9166213b3cSManuel Lauss static int db1x_card_inserted(struct db1x_pcmcia_sock *sock) 9266213b3cSManuel Lauss { 9366213b3cSManuel Lauss switch (sock->board_type) { 9466213b3cSManuel Lauss case BOARD_TYPE_DB1200: 9566213b3cSManuel Lauss return db1200_card_inserted(sock); 9664cd04d0SManuel Lauss case BOARD_TYPE_DB1300: 9764cd04d0SManuel Lauss return db1300_card_inserted(sock); 9866213b3cSManuel Lauss default: 9966213b3cSManuel Lauss return db1000_card_inserted(sock); 10066213b3cSManuel Lauss } 10166213b3cSManuel Lauss } 10266213b3cSManuel Lauss 10366213b3cSManuel Lauss /* STSCHG tends to bounce heavily when cards are inserted/ejected. 10466213b3cSManuel Lauss * To avoid this, the interrupt is normally disabled and only enabled 10566213b3cSManuel Lauss * after reset to a card has been de-asserted. 10666213b3cSManuel Lauss */ 10766213b3cSManuel Lauss static inline void set_stschg(struct db1x_pcmcia_sock *sock, int en) 10866213b3cSManuel Lauss { 10966213b3cSManuel Lauss if (sock->stschg_irq != -1) { 11066213b3cSManuel Lauss if (en) 11166213b3cSManuel Lauss enable_irq(sock->stschg_irq); 11266213b3cSManuel Lauss else 11366213b3cSManuel Lauss disable_irq(sock->stschg_irq); 11466213b3cSManuel Lauss } 11566213b3cSManuel Lauss } 11666213b3cSManuel Lauss 11766213b3cSManuel Lauss static irqreturn_t db1000_pcmcia_cdirq(int irq, void *data) 11866213b3cSManuel Lauss { 11966213b3cSManuel Lauss struct db1x_pcmcia_sock *sock = data; 12066213b3cSManuel Lauss 12166213b3cSManuel Lauss pcmcia_parse_events(&sock->socket, SS_DETECT); 12266213b3cSManuel Lauss 12366213b3cSManuel Lauss return IRQ_HANDLED; 12466213b3cSManuel Lauss } 12566213b3cSManuel Lauss 12666213b3cSManuel Lauss static irqreturn_t db1000_pcmcia_stschgirq(int irq, void *data) 12766213b3cSManuel Lauss { 12866213b3cSManuel Lauss struct db1x_pcmcia_sock *sock = data; 12966213b3cSManuel Lauss 13066213b3cSManuel Lauss pcmcia_parse_events(&sock->socket, SS_STSCHG); 13166213b3cSManuel Lauss 13266213b3cSManuel Lauss return IRQ_HANDLED; 13366213b3cSManuel Lauss } 13466213b3cSManuel Lauss 13566213b3cSManuel Lauss /* Db/Pb1200 have separate per-socket insertion and ejection 13666213b3cSManuel Lauss * interrupts which stay asserted as long as the card is 13766213b3cSManuel Lauss * inserted/missing. The one which caused us to be called 13866213b3cSManuel Lauss * needs to be disabled and the other one enabled. 13966213b3cSManuel Lauss */ 140cc10815eSManuel Lauss static irqreturn_t db1200_pcmcia_cdirq(int irq, void *data) 141cc10815eSManuel Lauss { 142cc10815eSManuel Lauss disable_irq_nosync(irq); 143cc10815eSManuel Lauss return IRQ_WAKE_THREAD; 14466213b3cSManuel Lauss } 14566213b3cSManuel Lauss 146cc10815eSManuel Lauss static irqreturn_t db1200_pcmcia_cdirq_fn(int irq, void *data) 147cc10815eSManuel Lauss { 148cc10815eSManuel Lauss struct db1x_pcmcia_sock *sock = data; 149cc10815eSManuel Lauss 150cc10815eSManuel Lauss /* Wait a bit for the signals to stop bouncing. */ 151cc10815eSManuel Lauss msleep(100); 152cc10815eSManuel Lauss if (irq == sock->insert_irq) 153cc10815eSManuel Lauss enable_irq(sock->eject_irq); 154cc10815eSManuel Lauss else 155cc10815eSManuel Lauss enable_irq(sock->insert_irq); 156cc10815eSManuel Lauss 15766213b3cSManuel Lauss pcmcia_parse_events(&sock->socket, SS_DETECT); 15866213b3cSManuel Lauss 15966213b3cSManuel Lauss return IRQ_HANDLED; 16066213b3cSManuel Lauss } 16166213b3cSManuel Lauss 16266213b3cSManuel Lauss static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock) 16366213b3cSManuel Lauss { 16466213b3cSManuel Lauss int ret; 16566213b3cSManuel Lauss 16666213b3cSManuel Lauss if (sock->stschg_irq != -1) { 16766213b3cSManuel Lauss ret = request_irq(sock->stschg_irq, db1000_pcmcia_stschgirq, 16866213b3cSManuel Lauss 0, "pcmcia_stschg", sock); 16966213b3cSManuel Lauss if (ret) 17066213b3cSManuel Lauss return ret; 17166213b3cSManuel Lauss } 17266213b3cSManuel Lauss 17366213b3cSManuel Lauss /* Db/Pb1200 have separate per-socket insertion and ejection 17466213b3cSManuel Lauss * interrupts, which should show edge behaviour but don't. 17566213b3cSManuel Lauss * So interrupts are disabled until both insertion and 17666213b3cSManuel Lauss * ejection handler have been registered and the currently 17766213b3cSManuel Lauss * active one disabled. 17866213b3cSManuel Lauss */ 17964cd04d0SManuel Lauss if ((sock->board_type == BOARD_TYPE_DB1200) || 18064cd04d0SManuel Lauss (sock->board_type == BOARD_TYPE_DB1300)) { 181cc10815eSManuel Lauss ret = request_threaded_irq(sock->insert_irq, db1200_pcmcia_cdirq, 182cc10815eSManuel Lauss db1200_pcmcia_cdirq_fn, 0, "pcmcia_insert", sock); 1830000a539SManuel Lauss if (ret) 18466213b3cSManuel Lauss goto out1; 18566213b3cSManuel Lauss 186cc10815eSManuel Lauss ret = request_threaded_irq(sock->eject_irq, db1200_pcmcia_cdirq, 187cc10815eSManuel Lauss db1200_pcmcia_cdirq_fn, 0, "pcmcia_eject", sock); 18866213b3cSManuel Lauss if (ret) { 18966213b3cSManuel Lauss free_irq(sock->insert_irq, sock); 19066213b3cSManuel Lauss goto out1; 19166213b3cSManuel Lauss } 19266213b3cSManuel Lauss 1930000a539SManuel Lauss /* enable the currently silent one */ 19464cd04d0SManuel Lauss if (db1x_card_inserted(sock)) 1950000a539SManuel Lauss enable_irq(sock->eject_irq); 19666213b3cSManuel Lauss else 1970000a539SManuel Lauss enable_irq(sock->insert_irq); 19866213b3cSManuel Lauss } else { 19966213b3cSManuel Lauss /* all other (older) Db1x00 boards use a GPIO to show 20066213b3cSManuel Lauss * card detection status: use both-edge triggers. 20166213b3cSManuel Lauss */ 202dced35aeSThomas Gleixner irq_set_irq_type(sock->insert_irq, IRQ_TYPE_EDGE_BOTH); 20366213b3cSManuel Lauss ret = request_irq(sock->insert_irq, db1000_pcmcia_cdirq, 20466213b3cSManuel Lauss 0, "pcmcia_carddetect", sock); 20566213b3cSManuel Lauss 20666213b3cSManuel Lauss if (ret) 20766213b3cSManuel Lauss goto out1; 20866213b3cSManuel Lauss } 20966213b3cSManuel Lauss 21066213b3cSManuel Lauss return 0; /* all done */ 21166213b3cSManuel Lauss 21266213b3cSManuel Lauss out1: 21366213b3cSManuel Lauss if (sock->stschg_irq != -1) 21466213b3cSManuel Lauss free_irq(sock->stschg_irq, sock); 21566213b3cSManuel Lauss 21666213b3cSManuel Lauss return ret; 21766213b3cSManuel Lauss } 21866213b3cSManuel Lauss 21966213b3cSManuel Lauss static void db1x_pcmcia_free_irqs(struct db1x_pcmcia_sock *sock) 22066213b3cSManuel Lauss { 22166213b3cSManuel Lauss if (sock->stschg_irq != -1) 22266213b3cSManuel Lauss free_irq(sock->stschg_irq, sock); 22366213b3cSManuel Lauss 22466213b3cSManuel Lauss free_irq(sock->insert_irq, sock); 22566213b3cSManuel Lauss if (sock->eject_irq != -1) 22666213b3cSManuel Lauss free_irq(sock->eject_irq, sock); 22766213b3cSManuel Lauss } 22866213b3cSManuel Lauss 22966213b3cSManuel Lauss /* 23066213b3cSManuel Lauss * configure a PCMCIA socket on the Db1x00 series of boards (and 23166213b3cSManuel Lauss * compatibles). 23266213b3cSManuel Lauss * 23366213b3cSManuel Lauss * 2 external registers are involved: 23466213b3cSManuel Lauss * pcmcia_status (offset 0x04): bits [0:1/2:3]: read card voltage id 23566213b3cSManuel Lauss * pcmcia_control(offset 0x10): 23666213b3cSManuel Lauss * bits[0:1] set vcc for card 23766213b3cSManuel Lauss * bits[2:3] set vpp for card 23866213b3cSManuel Lauss * bit 4: enable data buffers 23966213b3cSManuel Lauss * bit 7: reset# for card 24066213b3cSManuel Lauss * add 8 for second socket. 24166213b3cSManuel Lauss */ 24266213b3cSManuel Lauss static int db1x_pcmcia_configure(struct pcmcia_socket *skt, 24366213b3cSManuel Lauss struct socket_state_t *state) 24466213b3cSManuel Lauss { 24566213b3cSManuel Lauss struct db1x_pcmcia_sock *sock = to_db1x_socket(skt); 24666213b3cSManuel Lauss unsigned short cr_clr, cr_set; 24766213b3cSManuel Lauss unsigned int changed; 24866213b3cSManuel Lauss int v, p, ret; 24966213b3cSManuel Lauss 25066213b3cSManuel Lauss /* card voltage setup */ 25166213b3cSManuel Lauss cr_clr = (0xf << (sock->nr * 8)); /* clear voltage settings */ 25266213b3cSManuel Lauss cr_set = 0; 25366213b3cSManuel Lauss v = p = ret = 0; 25466213b3cSManuel Lauss 25566213b3cSManuel Lauss switch (state->Vcc) { 25666213b3cSManuel Lauss case 50: 25766213b3cSManuel Lauss ++v; 25866213b3cSManuel Lauss case 33: 25966213b3cSManuel Lauss ++v; 26066213b3cSManuel Lauss case 0: 26166213b3cSManuel Lauss break; 26266213b3cSManuel Lauss default: 26366213b3cSManuel Lauss printk(KERN_INFO "pcmcia%d unsupported Vcc %d\n", 26466213b3cSManuel Lauss sock->nr, state->Vcc); 26566213b3cSManuel Lauss } 26666213b3cSManuel Lauss 26766213b3cSManuel Lauss switch (state->Vpp) { 26866213b3cSManuel Lauss case 12: 26966213b3cSManuel Lauss ++p; 27066213b3cSManuel Lauss case 33: 27166213b3cSManuel Lauss case 50: 27266213b3cSManuel Lauss ++p; 27366213b3cSManuel Lauss case 0: 27466213b3cSManuel Lauss break; 27566213b3cSManuel Lauss default: 27666213b3cSManuel Lauss printk(KERN_INFO "pcmcia%d unsupported Vpp %d\n", 27766213b3cSManuel Lauss sock->nr, state->Vpp); 27866213b3cSManuel Lauss } 27966213b3cSManuel Lauss 28066213b3cSManuel Lauss /* sanity check: Vpp must be 0, 12, or Vcc */ 28166213b3cSManuel Lauss if (((state->Vcc == 33) && (state->Vpp == 50)) || 28266213b3cSManuel Lauss ((state->Vcc == 50) && (state->Vpp == 33))) { 28366213b3cSManuel Lauss printk(KERN_INFO "pcmcia%d bad Vcc/Vpp combo (%d %d)\n", 28466213b3cSManuel Lauss sock->nr, state->Vcc, state->Vpp); 28566213b3cSManuel Lauss v = p = 0; 28666213b3cSManuel Lauss ret = -EINVAL; 28766213b3cSManuel Lauss } 28866213b3cSManuel Lauss 28966213b3cSManuel Lauss /* create new voltage code */ 29064cd04d0SManuel Lauss if (sock->board_type != BOARD_TYPE_DB1300) 29166213b3cSManuel Lauss cr_set |= ((v << 2) | p) << (sock->nr * 8); 29266213b3cSManuel Lauss 29366213b3cSManuel Lauss changed = state->flags ^ sock->old_flags; 29466213b3cSManuel Lauss 29566213b3cSManuel Lauss if (changed & SS_RESET) { 29666213b3cSManuel Lauss if (state->flags & SS_RESET) { 29766213b3cSManuel Lauss set_stschg(sock, 0); 29866213b3cSManuel Lauss /* assert reset, disable io buffers */ 29966213b3cSManuel Lauss cr_clr |= (1 << (7 + (sock->nr * 8))); 30066213b3cSManuel Lauss cr_clr |= (1 << (4 + (sock->nr * 8))); 30166213b3cSManuel Lauss } else { 30266213b3cSManuel Lauss /* de-assert reset, enable io buffers */ 30366213b3cSManuel Lauss cr_set |= 1 << (7 + (sock->nr * 8)); 30466213b3cSManuel Lauss cr_set |= 1 << (4 + (sock->nr * 8)); 30566213b3cSManuel Lauss } 30666213b3cSManuel Lauss } 30766213b3cSManuel Lauss 30866213b3cSManuel Lauss /* update PCMCIA configuration */ 30966213b3cSManuel Lauss bcsr_mod(BCSR_PCMCIA, cr_clr, cr_set); 31066213b3cSManuel Lauss 31166213b3cSManuel Lauss sock->old_flags = state->flags; 31266213b3cSManuel Lauss 31366213b3cSManuel Lauss /* reset was taken away: give card time to initialize properly */ 31466213b3cSManuel Lauss if ((changed & SS_RESET) && !(state->flags & SS_RESET)) { 31566213b3cSManuel Lauss msleep(500); 31666213b3cSManuel Lauss set_stschg(sock, 1); 31766213b3cSManuel Lauss } 31866213b3cSManuel Lauss 31966213b3cSManuel Lauss return ret; 32066213b3cSManuel Lauss } 32166213b3cSManuel Lauss 32266213b3cSManuel Lauss /* VCC bits at [3:2]/[11:10] */ 32366213b3cSManuel Lauss #define GET_VCC(cr, socknr) \ 32466213b3cSManuel Lauss ((((cr) >> 2) >> ((socknr) * 8)) & 3) 32566213b3cSManuel Lauss 32666213b3cSManuel Lauss /* VS bits at [0:1]/[3:2] */ 32766213b3cSManuel Lauss #define GET_VS(sr, socknr) \ 32866213b3cSManuel Lauss (((sr) >> (2 * (socknr))) & 3) 32966213b3cSManuel Lauss 33066213b3cSManuel Lauss /* reset bits at [7]/[15] */ 33166213b3cSManuel Lauss #define GET_RESET(cr, socknr) \ 33266213b3cSManuel Lauss ((cr) & (1 << (7 + (8 * (socknr))))) 33366213b3cSManuel Lauss 33466213b3cSManuel Lauss static int db1x_pcmcia_get_status(struct pcmcia_socket *skt, 33566213b3cSManuel Lauss unsigned int *value) 33666213b3cSManuel Lauss { 33766213b3cSManuel Lauss struct db1x_pcmcia_sock *sock = to_db1x_socket(skt); 33866213b3cSManuel Lauss unsigned short cr, sr; 33966213b3cSManuel Lauss unsigned int status; 34066213b3cSManuel Lauss 34166213b3cSManuel Lauss status = db1x_card_inserted(sock) ? SS_DETECT : 0; 34266213b3cSManuel Lauss 34366213b3cSManuel Lauss cr = bcsr_read(BCSR_PCMCIA); 34466213b3cSManuel Lauss sr = bcsr_read(BCSR_STATUS); 34566213b3cSManuel Lauss 34666213b3cSManuel Lauss /* PB1100/PB1500: voltage key bits are at [5:4] */ 34766213b3cSManuel Lauss if (sock->board_type == BOARD_TYPE_PB1100) 34866213b3cSManuel Lauss sr >>= 4; 34966213b3cSManuel Lauss 35066213b3cSManuel Lauss /* determine card type */ 35166213b3cSManuel Lauss switch (GET_VS(sr, sock->nr)) { 35266213b3cSManuel Lauss case 0: 35366213b3cSManuel Lauss case 2: 35466213b3cSManuel Lauss status |= SS_3VCARD; /* 3V card */ 35566213b3cSManuel Lauss case 3: 35666213b3cSManuel Lauss break; /* 5V card: set nothing */ 35766213b3cSManuel Lauss default: 35866213b3cSManuel Lauss status |= SS_XVCARD; /* treated as unsupported in core */ 35966213b3cSManuel Lauss } 36066213b3cSManuel Lauss 36166213b3cSManuel Lauss /* if Vcc is not zero, we have applied power to a card */ 36266213b3cSManuel Lauss status |= GET_VCC(cr, sock->nr) ? SS_POWERON : 0; 36366213b3cSManuel Lauss 36464cd04d0SManuel Lauss /* DB1300: power always on, but don't tell when no card present */ 36564cd04d0SManuel Lauss if ((sock->board_type == BOARD_TYPE_DB1300) && (status & SS_DETECT)) 36664cd04d0SManuel Lauss status = SS_POWERON | SS_3VCARD | SS_DETECT; 36764cd04d0SManuel Lauss 36866213b3cSManuel Lauss /* reset de-asserted? then we're ready */ 36966213b3cSManuel Lauss status |= (GET_RESET(cr, sock->nr)) ? SS_READY : SS_RESET; 37066213b3cSManuel Lauss 37166213b3cSManuel Lauss *value = status; 37266213b3cSManuel Lauss 37366213b3cSManuel Lauss return 0; 37466213b3cSManuel Lauss } 37566213b3cSManuel Lauss 37666213b3cSManuel Lauss static int db1x_pcmcia_sock_init(struct pcmcia_socket *skt) 37766213b3cSManuel Lauss { 37866213b3cSManuel Lauss return 0; 37966213b3cSManuel Lauss } 38066213b3cSManuel Lauss 38166213b3cSManuel Lauss static int db1x_pcmcia_sock_suspend(struct pcmcia_socket *skt) 38266213b3cSManuel Lauss { 38366213b3cSManuel Lauss return 0; 38466213b3cSManuel Lauss } 38566213b3cSManuel Lauss 38666213b3cSManuel Lauss static int au1x00_pcmcia_set_io_map(struct pcmcia_socket *skt, 38766213b3cSManuel Lauss struct pccard_io_map *map) 38866213b3cSManuel Lauss { 38966213b3cSManuel Lauss struct db1x_pcmcia_sock *sock = to_db1x_socket(skt); 39066213b3cSManuel Lauss 39166213b3cSManuel Lauss map->start = (u32)sock->virt_io; 39266213b3cSManuel Lauss map->stop = map->start + IO_MAP_SIZE; 39366213b3cSManuel Lauss 39466213b3cSManuel Lauss return 0; 39566213b3cSManuel Lauss } 39666213b3cSManuel Lauss 39766213b3cSManuel Lauss static int au1x00_pcmcia_set_mem_map(struct pcmcia_socket *skt, 39866213b3cSManuel Lauss struct pccard_mem_map *map) 39966213b3cSManuel Lauss { 40066213b3cSManuel Lauss struct db1x_pcmcia_sock *sock = to_db1x_socket(skt); 40166213b3cSManuel Lauss 40266213b3cSManuel Lauss if (map->flags & MAP_ATTRIB) 40366213b3cSManuel Lauss map->static_start = sock->phys_attr + map->card_start; 40466213b3cSManuel Lauss else 40566213b3cSManuel Lauss map->static_start = sock->phys_mem + map->card_start; 40666213b3cSManuel Lauss 40766213b3cSManuel Lauss return 0; 40866213b3cSManuel Lauss } 40966213b3cSManuel Lauss 41066213b3cSManuel Lauss static struct pccard_operations db1x_pcmcia_operations = { 41166213b3cSManuel Lauss .init = db1x_pcmcia_sock_init, 41266213b3cSManuel Lauss .suspend = db1x_pcmcia_sock_suspend, 41366213b3cSManuel Lauss .get_status = db1x_pcmcia_get_status, 41466213b3cSManuel Lauss .set_socket = db1x_pcmcia_configure, 41566213b3cSManuel Lauss .set_io_map = au1x00_pcmcia_set_io_map, 41666213b3cSManuel Lauss .set_mem_map = au1x00_pcmcia_set_mem_map, 41766213b3cSManuel Lauss }; 41866213b3cSManuel Lauss 41934cdf25aSBill Pemberton static int db1x_pcmcia_socket_probe(struct platform_device *pdev) 42066213b3cSManuel Lauss { 42166213b3cSManuel Lauss struct db1x_pcmcia_sock *sock; 42266213b3cSManuel Lauss struct resource *r; 42366213b3cSManuel Lauss int ret, bid; 42466213b3cSManuel Lauss 42566213b3cSManuel Lauss sock = kzalloc(sizeof(struct db1x_pcmcia_sock), GFP_KERNEL); 42666213b3cSManuel Lauss if (!sock) 42766213b3cSManuel Lauss return -ENOMEM; 42866213b3cSManuel Lauss 42966213b3cSManuel Lauss sock->nr = pdev->id; 43066213b3cSManuel Lauss 43166213b3cSManuel Lauss bid = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)); 43266213b3cSManuel Lauss switch (bid) { 43366213b3cSManuel Lauss case BCSR_WHOAMI_PB1500: 43466213b3cSManuel Lauss case BCSR_WHOAMI_PB1500R2: 43566213b3cSManuel Lauss case BCSR_WHOAMI_PB1100: 43666213b3cSManuel Lauss sock->board_type = BOARD_TYPE_PB1100; 43766213b3cSManuel Lauss break; 43866213b3cSManuel Lauss case BCSR_WHOAMI_DB1000 ... BCSR_WHOAMI_PB1550_SDR: 43966213b3cSManuel Lauss sock->board_type = BOARD_TYPE_DEFAULT; 44066213b3cSManuel Lauss break; 44166213b3cSManuel Lauss case BCSR_WHOAMI_PB1200 ... BCSR_WHOAMI_DB1200: 44266213b3cSManuel Lauss sock->board_type = BOARD_TYPE_DB1200; 44366213b3cSManuel Lauss break; 44464cd04d0SManuel Lauss case BCSR_WHOAMI_DB1300: 44564cd04d0SManuel Lauss sock->board_type = BOARD_TYPE_DB1300; 44664cd04d0SManuel Lauss break; 44766213b3cSManuel Lauss default: 44866213b3cSManuel Lauss printk(KERN_INFO "db1xxx-ss: unknown board %d!\n", bid); 44966213b3cSManuel Lauss ret = -ENODEV; 45066213b3cSManuel Lauss goto out0; 45166213b3cSManuel Lauss }; 45266213b3cSManuel Lauss 45366213b3cSManuel Lauss /* 45466213b3cSManuel Lauss * gather resources necessary and optional nice-to-haves to 45566213b3cSManuel Lauss * operate a socket: 45666213b3cSManuel Lauss * This includes IRQs for Carddetection/ejection, the card 45766213b3cSManuel Lauss * itself and optional status change detection. 45866213b3cSManuel Lauss * Also, the memory areas covered by a socket. For these 459f25e188cSManuel Lauss * we require the real 36bit addresses (see the au1000.h 46066213b3cSManuel Lauss * header for more information). 46166213b3cSManuel Lauss */ 46266213b3cSManuel Lauss 46366213b3cSManuel Lauss /* card: irq assigned to the card itself. */ 46466213b3cSManuel Lauss r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "card"); 46566213b3cSManuel Lauss sock->card_irq = r ? r->start : 0; 46666213b3cSManuel Lauss 467e34b6fcfSManuel Lauss /* insert: irq which triggers on card insertion/ejection 468e34b6fcfSManuel Lauss * BIG FAT NOTE: on DB1000/1100/1500/1550 we pass a GPIO here! 469e34b6fcfSManuel Lauss */ 47066213b3cSManuel Lauss r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "insert"); 47166213b3cSManuel Lauss sock->insert_irq = r ? r->start : -1; 472e34b6fcfSManuel Lauss if (sock->board_type == BOARD_TYPE_DEFAULT) { 473e34b6fcfSManuel Lauss sock->insert_gpio = r ? r->start : -1; 474e34b6fcfSManuel Lauss sock->insert_irq = r ? gpio_to_irq(r->start) : -1; 475e34b6fcfSManuel Lauss } 47666213b3cSManuel Lauss 47766213b3cSManuel Lauss /* stschg: irq which trigger on card status change (optional) */ 47866213b3cSManuel Lauss r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "stschg"); 47966213b3cSManuel Lauss sock->stschg_irq = r ? r->start : -1; 48066213b3cSManuel Lauss 48166213b3cSManuel Lauss /* eject: irq which triggers on ejection (DB1200/PB1200 only) */ 48266213b3cSManuel Lauss r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "eject"); 48366213b3cSManuel Lauss sock->eject_irq = r ? r->start : -1; 48466213b3cSManuel Lauss 48566213b3cSManuel Lauss ret = -ENODEV; 48666213b3cSManuel Lauss 487f25e188cSManuel Lauss /* 36bit PCMCIA Attribute area address */ 48811b897cfSManuel Lauss r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr"); 48966213b3cSManuel Lauss if (!r) { 49066213b3cSManuel Lauss printk(KERN_ERR "pcmcia%d has no 'pseudo-attr' resource!\n", 49166213b3cSManuel Lauss sock->nr); 49266213b3cSManuel Lauss goto out0; 49366213b3cSManuel Lauss } 49466213b3cSManuel Lauss sock->phys_attr = r->start; 49566213b3cSManuel Lauss 496f25e188cSManuel Lauss /* 36bit PCMCIA Memory area address */ 49711b897cfSManuel Lauss r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem"); 49866213b3cSManuel Lauss if (!r) { 49966213b3cSManuel Lauss printk(KERN_ERR "pcmcia%d has no 'pseudo-mem' resource!\n", 50066213b3cSManuel Lauss sock->nr); 50166213b3cSManuel Lauss goto out0; 50266213b3cSManuel Lauss } 50366213b3cSManuel Lauss sock->phys_mem = r->start; 50466213b3cSManuel Lauss 505f25e188cSManuel Lauss /* 36bit PCMCIA IO area address */ 50611b897cfSManuel Lauss r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io"); 50766213b3cSManuel Lauss if (!r) { 50866213b3cSManuel Lauss printk(KERN_ERR "pcmcia%d has no 'pseudo-io' resource!\n", 50966213b3cSManuel Lauss sock->nr); 51066213b3cSManuel Lauss goto out0; 51166213b3cSManuel Lauss } 51266213b3cSManuel Lauss sock->phys_io = r->start; 51366213b3cSManuel Lauss 51466213b3cSManuel Lauss /* 51566213b3cSManuel Lauss * PCMCIA client drivers use the inb/outb macros to access 51666213b3cSManuel Lauss * the IO registers. Since mips_io_port_base is added 51766213b3cSManuel Lauss * to the access address of the mips implementation of 51866213b3cSManuel Lauss * inb/outb, we need to subtract it here because we want 51966213b3cSManuel Lauss * to access the I/O or MEM address directly, without 52066213b3cSManuel Lauss * going through this "mips_io_port_base" mechanism. 52166213b3cSManuel Lauss */ 52211b897cfSManuel Lauss sock->virt_io = (void *)(ioremap(sock->phys_io, IO_MAP_SIZE) - 52366213b3cSManuel Lauss mips_io_port_base); 52466213b3cSManuel Lauss 52566213b3cSManuel Lauss if (!sock->virt_io) { 52666213b3cSManuel Lauss printk(KERN_ERR "pcmcia%d: cannot remap IO area\n", 52766213b3cSManuel Lauss sock->nr); 52866213b3cSManuel Lauss ret = -ENOMEM; 52966213b3cSManuel Lauss goto out0; 53066213b3cSManuel Lauss } 53166213b3cSManuel Lauss 53266213b3cSManuel Lauss sock->socket.ops = &db1x_pcmcia_operations; 53366213b3cSManuel Lauss sock->socket.owner = THIS_MODULE; 53466213b3cSManuel Lauss sock->socket.pci_irq = sock->card_irq; 53566213b3cSManuel Lauss sock->socket.features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD; 53666213b3cSManuel Lauss sock->socket.map_size = MEM_MAP_SIZE; 53766213b3cSManuel Lauss sock->socket.io_offset = (unsigned long)sock->virt_io; 53866213b3cSManuel Lauss sock->socket.dev.parent = &pdev->dev; 53966213b3cSManuel Lauss sock->socket.resource_ops = &pccard_static_ops; 54066213b3cSManuel Lauss 54166213b3cSManuel Lauss platform_set_drvdata(pdev, sock); 54266213b3cSManuel Lauss 54366213b3cSManuel Lauss ret = db1x_pcmcia_setup_irqs(sock); 54466213b3cSManuel Lauss if (ret) { 54566213b3cSManuel Lauss printk(KERN_ERR "pcmcia%d cannot setup interrupts\n", 54666213b3cSManuel Lauss sock->nr); 54766213b3cSManuel Lauss goto out1; 54866213b3cSManuel Lauss } 54966213b3cSManuel Lauss 55066213b3cSManuel Lauss set_stschg(sock, 0); 55166213b3cSManuel Lauss 55266213b3cSManuel Lauss ret = pcmcia_register_socket(&sock->socket); 55366213b3cSManuel Lauss if (ret) { 55466213b3cSManuel Lauss printk(KERN_ERR "pcmcia%d failed to register\n", sock->nr); 55566213b3cSManuel Lauss goto out2; 55666213b3cSManuel Lauss } 55766213b3cSManuel Lauss 55811b897cfSManuel Lauss printk(KERN_INFO "Alchemy Db/Pb1xxx pcmcia%d @ io/attr/mem %09llx" 55911b897cfSManuel Lauss "(%p) %09llx %09llx card/insert/stschg/eject irqs @ %d " 56066213b3cSManuel Lauss "%d %d %d\n", sock->nr, sock->phys_io, sock->virt_io, 56166213b3cSManuel Lauss sock->phys_attr, sock->phys_mem, sock->card_irq, 56266213b3cSManuel Lauss sock->insert_irq, sock->stschg_irq, sock->eject_irq); 56366213b3cSManuel Lauss 56466213b3cSManuel Lauss return 0; 56566213b3cSManuel Lauss 56666213b3cSManuel Lauss out2: 56766213b3cSManuel Lauss db1x_pcmcia_free_irqs(sock); 56866213b3cSManuel Lauss out1: 56966213b3cSManuel Lauss iounmap((void *)(sock->virt_io + (u32)mips_io_port_base)); 57066213b3cSManuel Lauss out0: 57166213b3cSManuel Lauss kfree(sock); 57266213b3cSManuel Lauss return ret; 57366213b3cSManuel Lauss } 57466213b3cSManuel Lauss 575e765a02cSBill Pemberton static int db1x_pcmcia_socket_remove(struct platform_device *pdev) 57666213b3cSManuel Lauss { 57766213b3cSManuel Lauss struct db1x_pcmcia_sock *sock = platform_get_drvdata(pdev); 57866213b3cSManuel Lauss 57966213b3cSManuel Lauss db1x_pcmcia_free_irqs(sock); 58066213b3cSManuel Lauss pcmcia_unregister_socket(&sock->socket); 58166213b3cSManuel Lauss iounmap((void *)(sock->virt_io + (u32)mips_io_port_base)); 58266213b3cSManuel Lauss kfree(sock); 58366213b3cSManuel Lauss 58466213b3cSManuel Lauss return 0; 58566213b3cSManuel Lauss } 58666213b3cSManuel Lauss 58766213b3cSManuel Lauss static struct platform_driver db1x_pcmcia_socket_driver = { 58866213b3cSManuel Lauss .driver = { 58966213b3cSManuel Lauss .name = "db1xxx_pcmcia", 59066213b3cSManuel Lauss }, 59166213b3cSManuel Lauss .probe = db1x_pcmcia_socket_probe, 59296364e3aSBill Pemberton .remove = db1x_pcmcia_socket_remove, 59366213b3cSManuel Lauss }; 59466213b3cSManuel Lauss 5955d95f8e2SAxel Lin module_platform_driver(db1x_pcmcia_socket_driver); 59666213b3cSManuel Lauss 59766213b3cSManuel Lauss MODULE_LICENSE("GPL"); 59866213b3cSManuel Lauss MODULE_DESCRIPTION("PCMCIA Socket Services for Alchemy Db/Pb1x00 boards"); 59966213b3cSManuel Lauss MODULE_AUTHOR("Manuel Lauss"); 600