^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) * PCMCIA socket code for the MyCable XXS1500 system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2009 Manuel Lauss <manuel.lauss@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/resource.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <pcmcia/ss.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <pcmcia/cistpl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/mach-au1x00/au1000.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define MEM_MAP_SIZE 0x400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define IO_MAP_SIZE 0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * 3.3V cards only; all interfacing is done via gpios:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * 0/1: carddetect (00 = card present, xx = huh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * 4: card irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * 204: reset (high-act)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * 205: buffer enable (low-act)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * 208/209: card voltage key (00,01,10,11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * 210: battwarn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * 211: batdead
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * 214: power (low-act)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define GPIO_CDA 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define GPIO_CDB 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define GPIO_CARDIRQ 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define GPIO_RESET 204
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define GPIO_OUTEN 205
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define GPIO_VSL 208
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define GPIO_VSH 209
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define GPIO_BATTDEAD 210
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define GPIO_BATTWARN 211
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define GPIO_POWER 214
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct xxs1500_pcmcia_sock {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct pcmcia_socket socket;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) void *virt_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) phys_addr_t phys_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) phys_addr_t phys_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) phys_addr_t phys_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* previous flags for set_socket() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned int old_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define to_xxs_socket(x) container_of(x, struct xxs1500_pcmcia_sock, socket)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static irqreturn_t cdirq(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct xxs1500_pcmcia_sock *sock = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) pcmcia_parse_events(&sock->socket, SS_DETECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int xxs1500_pcmcia_configure(struct pcmcia_socket *skt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct socket_state_t *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned int changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* power control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) switch (state->Vcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) gpio_set_value(GPIO_POWER, 1); /* power off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) case 33:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) gpio_set_value(GPIO_POWER, 0); /* power on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) case 50:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return -EINVAL;
^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) changed = state->flags ^ sock->old_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (changed & SS_RESET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (state->flags & SS_RESET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) gpio_set_value(GPIO_RESET, 1); /* assert reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) gpio_set_value(GPIO_OUTEN, 1); /* buffers off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) gpio_set_value(GPIO_RESET, 0); /* deassert reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) gpio_set_value(GPIO_OUTEN, 0); /* buffers on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) msleep(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) sock->old_flags = state->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int xxs1500_pcmcia_get_status(struct pcmcia_socket *skt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned int *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* check carddetects: GPIO[0:1] must both be low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (!gpio_get_value(GPIO_CDA) && !gpio_get_value(GPIO_CDB))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) status |= SS_DETECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* determine card voltage: GPIO[208:209] binary value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) i = (!!gpio_get_value(GPIO_VSL)) | ((!!gpio_get_value(GPIO_VSH)) << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) switch (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) status |= SS_3VCARD; /* 3V card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) case 3: /* 5V card, unsupported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) status |= SS_XVCARD; /* treated as unsupported in core */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* GPIO214: low active power switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) status |= gpio_get_value(GPIO_POWER) ? 0 : SS_POWERON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* GPIO204: high-active reset line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) status |= gpio_get_value(GPIO_RESET) ? SS_RESET : SS_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* other stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) status |= gpio_get_value(GPIO_BATTDEAD) ? 0 : SS_BATDEAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) status |= gpio_get_value(GPIO_BATTWARN) ? 0 : SS_BATWARN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) *value = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static int xxs1500_pcmcia_sock_init(struct pcmcia_socket *skt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) gpio_direction_input(GPIO_CDA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) gpio_direction_input(GPIO_CDB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) gpio_direction_input(GPIO_VSL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) gpio_direction_input(GPIO_VSH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) gpio_direction_input(GPIO_BATTDEAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) gpio_direction_input(GPIO_BATTWARN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) gpio_direction_output(GPIO_RESET, 1); /* assert reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) gpio_direction_output(GPIO_OUTEN, 1); /* disable buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) gpio_direction_output(GPIO_POWER, 1); /* power off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int xxs1500_pcmcia_sock_suspend(struct pcmcia_socket *skt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 0;
^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) static int au1x00_pcmcia_set_io_map(struct pcmcia_socket *skt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct pccard_io_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) map->start = (u32)sock->virt_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) map->stop = map->start + IO_MAP_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static int au1x00_pcmcia_set_mem_map(struct pcmcia_socket *skt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct pccard_mem_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (map->flags & MAP_ATTRIB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) map->static_start = sock->phys_attr + map->card_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) map->static_start = sock->phys_mem + map->card_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static struct pccard_operations xxs1500_pcmcia_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .init = xxs1500_pcmcia_sock_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .suspend = xxs1500_pcmcia_sock_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .get_status = xxs1500_pcmcia_get_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .set_socket = xxs1500_pcmcia_configure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .set_io_map = au1x00_pcmcia_set_io_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .set_mem_map = au1x00_pcmcia_set_mem_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int xxs1500_pcmcia_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct xxs1500_pcmcia_sock *sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct resource *r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) int ret, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) sock = kzalloc(sizeof(struct xxs1500_pcmcia_sock), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (!sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* 36bit PCMCIA Attribute area address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (!r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) dev_err(&pdev->dev, "missing 'pcmcia-attr' resource!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) goto out0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) sock->phys_attr = r->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* 36bit PCMCIA Memory area address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (!r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) dev_err(&pdev->dev, "missing 'pcmcia-mem' resource!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) goto out0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) sock->phys_mem = r->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* 36bit PCMCIA IO area address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) dev_err(&pdev->dev, "missing 'pcmcia-io' resource!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) goto out0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) sock->phys_io = r->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * PCMCIA client drivers use the inb/outb macros to access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * the IO registers. Since mips_io_port_base is added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * to the access address of the mips implementation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * inb/outb, we need to subtract it here because we want
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * to access the I/O or MEM address directly, without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * going through this "mips_io_port_base" mechanism.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) sock->virt_io = (void *)(ioremap(sock->phys_io, IO_MAP_SIZE) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) mips_io_port_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (!sock->virt_io) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) dev_err(&pdev->dev, "cannot remap IO area\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) goto out0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) sock->socket.ops = &xxs1500_pcmcia_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) sock->socket.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) sock->socket.pci_irq = gpio_to_irq(GPIO_CARDIRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) sock->socket.features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) sock->socket.map_size = MEM_MAP_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) sock->socket.io_offset = (unsigned long)sock->virt_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) sock->socket.dev.parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) sock->socket.resource_ops = &pccard_static_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) platform_set_drvdata(pdev, sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* setup carddetect irq: use one of the 2 GPIOs as an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * edge detector.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) irq = gpio_to_irq(GPIO_CDA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ret = request_irq(irq, cdirq, 0, "pcmcia_carddetect", sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) dev_err(&pdev->dev, "cannot setup cd irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) goto out1;
^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) ret = pcmcia_register_socket(&sock->socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) dev_err(&pdev->dev, "failed to register\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) goto out2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) printk(KERN_INFO "MyCable XXS1500 PCMCIA socket services\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) out2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) free_irq(gpio_to_irq(GPIO_CDA), sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) out1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) out0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) kfree(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static int xxs1500_pcmcia_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct xxs1500_pcmcia_sock *sock = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) pcmcia_unregister_socket(&sock->socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) free_irq(gpio_to_irq(GPIO_CDA), sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) kfree(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static struct platform_driver xxs1500_pcmcia_socket_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) .name = "xxs1500_pcmcia",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) .probe = xxs1500_pcmcia_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) .remove = xxs1500_pcmcia_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) module_platform_driver(xxs1500_pcmcia_socket_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) MODULE_DESCRIPTION("PCMCIA Socket Services for MyCable XXS1500 systems");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) MODULE_AUTHOR("Manuel Lauss");