0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include <linux/delay.h>
0026 #include <linux/gpio.h>
0027 #include <linux/interrupt.h>
0028 #include <linux/pm.h>
0029 #include <linux/module.h>
0030 #include <linux/platform_device.h>
0031 #include <linux/resource.h>
0032 #include <linux/slab.h>
0033 #include <linux/spinlock.h>
0034
0035 #include <pcmcia/ss.h>
0036
0037 #include <asm/mach-au1x00/au1000.h>
0038 #include <asm/mach-db1x00/bcsr.h>
0039
0040 #define MEM_MAP_SIZE 0x400000
0041 #define IO_MAP_SIZE 0x1000
0042
0043 struct db1x_pcmcia_sock {
0044 struct pcmcia_socket socket;
0045 int nr;
0046 void *virt_io;
0047
0048 phys_addr_t phys_io;
0049 phys_addr_t phys_attr;
0050 phys_addr_t phys_mem;
0051
0052
0053 unsigned int old_flags;
0054
0055
0056 int insert_irq;
0057 int stschg_irq;
0058 int card_irq;
0059 int eject_irq;
0060 int insert_gpio;
0061
0062 #define BOARD_TYPE_DEFAULT 0
0063 #define BOARD_TYPE_DB1200 1
0064 #define BOARD_TYPE_PB1100 2
0065 #define BOARD_TYPE_DB1300 3
0066 int board_type;
0067 };
0068
0069 #define to_db1x_socket(x) container_of(x, struct db1x_pcmcia_sock, socket)
0070
0071 static int db1300_card_inserted(struct db1x_pcmcia_sock *sock)
0072 {
0073 return bcsr_read(BCSR_SIGSTAT) & (1 << 8);
0074 }
0075
0076
0077 static int db1200_card_inserted(struct db1x_pcmcia_sock *sock)
0078 {
0079 unsigned short sigstat;
0080
0081 sigstat = bcsr_read(BCSR_SIGSTAT);
0082 return sigstat & 1 << (8 + 2 * sock->nr);
0083 }
0084
0085
0086 static int db1000_card_inserted(struct db1x_pcmcia_sock *sock)
0087 {
0088 return !gpio_get_value(sock->insert_gpio);
0089 }
0090
0091 static int db1x_card_inserted(struct db1x_pcmcia_sock *sock)
0092 {
0093 switch (sock->board_type) {
0094 case BOARD_TYPE_DB1200:
0095 return db1200_card_inserted(sock);
0096 case BOARD_TYPE_DB1300:
0097 return db1300_card_inserted(sock);
0098 default:
0099 return db1000_card_inserted(sock);
0100 }
0101 }
0102
0103
0104
0105
0106
0107 static inline void set_stschg(struct db1x_pcmcia_sock *sock, int en)
0108 {
0109 if (sock->stschg_irq != -1) {
0110 if (en)
0111 enable_irq(sock->stschg_irq);
0112 else
0113 disable_irq(sock->stschg_irq);
0114 }
0115 }
0116
0117 static irqreturn_t db1000_pcmcia_cdirq(int irq, void *data)
0118 {
0119 struct db1x_pcmcia_sock *sock = data;
0120
0121 pcmcia_parse_events(&sock->socket, SS_DETECT);
0122
0123 return IRQ_HANDLED;
0124 }
0125
0126 static irqreturn_t db1000_pcmcia_stschgirq(int irq, void *data)
0127 {
0128 struct db1x_pcmcia_sock *sock = data;
0129
0130 pcmcia_parse_events(&sock->socket, SS_STSCHG);
0131
0132 return IRQ_HANDLED;
0133 }
0134
0135
0136
0137
0138
0139
0140 static irqreturn_t db1200_pcmcia_cdirq(int irq, void *data)
0141 {
0142 disable_irq_nosync(irq);
0143 return IRQ_WAKE_THREAD;
0144 }
0145
0146 static irqreturn_t db1200_pcmcia_cdirq_fn(int irq, void *data)
0147 {
0148 struct db1x_pcmcia_sock *sock = data;
0149
0150
0151 msleep(100);
0152 if (irq == sock->insert_irq)
0153 enable_irq(sock->eject_irq);
0154 else
0155 enable_irq(sock->insert_irq);
0156
0157 pcmcia_parse_events(&sock->socket, SS_DETECT);
0158
0159 return IRQ_HANDLED;
0160 }
0161
0162 static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)
0163 {
0164 int ret;
0165
0166 if (sock->stschg_irq != -1) {
0167 ret = request_irq(sock->stschg_irq, db1000_pcmcia_stschgirq,
0168 0, "pcmcia_stschg", sock);
0169 if (ret)
0170 return ret;
0171 }
0172
0173
0174
0175
0176
0177
0178
0179 if ((sock->board_type == BOARD_TYPE_DB1200) ||
0180 (sock->board_type == BOARD_TYPE_DB1300)) {
0181 ret = request_threaded_irq(sock->insert_irq, db1200_pcmcia_cdirq,
0182 db1200_pcmcia_cdirq_fn, 0, "pcmcia_insert", sock);
0183 if (ret)
0184 goto out1;
0185
0186 ret = request_threaded_irq(sock->eject_irq, db1200_pcmcia_cdirq,
0187 db1200_pcmcia_cdirq_fn, 0, "pcmcia_eject", sock);
0188 if (ret) {
0189 free_irq(sock->insert_irq, sock);
0190 goto out1;
0191 }
0192
0193
0194 if (db1x_card_inserted(sock))
0195 enable_irq(sock->eject_irq);
0196 else
0197 enable_irq(sock->insert_irq);
0198 } else {
0199
0200
0201
0202 irq_set_irq_type(sock->insert_irq, IRQ_TYPE_EDGE_BOTH);
0203 ret = request_irq(sock->insert_irq, db1000_pcmcia_cdirq,
0204 0, "pcmcia_carddetect", sock);
0205
0206 if (ret)
0207 goto out1;
0208 }
0209
0210 return 0;
0211
0212 out1:
0213 if (sock->stschg_irq != -1)
0214 free_irq(sock->stschg_irq, sock);
0215
0216 return ret;
0217 }
0218
0219 static void db1x_pcmcia_free_irqs(struct db1x_pcmcia_sock *sock)
0220 {
0221 if (sock->stschg_irq != -1)
0222 free_irq(sock->stschg_irq, sock);
0223
0224 free_irq(sock->insert_irq, sock);
0225 if (sock->eject_irq != -1)
0226 free_irq(sock->eject_irq, sock);
0227 }
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242 static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
0243 struct socket_state_t *state)
0244 {
0245 struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);
0246 unsigned short cr_clr, cr_set;
0247 unsigned int changed;
0248 int v, p, ret;
0249
0250
0251 cr_clr = (0xf << (sock->nr * 8));
0252 cr_set = 0;
0253 v = p = ret = 0;
0254
0255 switch (state->Vcc) {
0256 case 50:
0257 ++v;
0258 fallthrough;
0259 case 33:
0260 ++v;
0261 fallthrough;
0262 case 0:
0263 break;
0264 default:
0265 printk(KERN_INFO "pcmcia%d unsupported Vcc %d\n",
0266 sock->nr, state->Vcc);
0267 }
0268
0269 switch (state->Vpp) {
0270 case 12:
0271 ++p;
0272 fallthrough;
0273 case 33:
0274 case 50:
0275 ++p;
0276 fallthrough;
0277 case 0:
0278 break;
0279 default:
0280 printk(KERN_INFO "pcmcia%d unsupported Vpp %d\n",
0281 sock->nr, state->Vpp);
0282 }
0283
0284
0285 if (((state->Vcc == 33) && (state->Vpp == 50)) ||
0286 ((state->Vcc == 50) && (state->Vpp == 33))) {
0287 printk(KERN_INFO "pcmcia%d bad Vcc/Vpp combo (%d %d)\n",
0288 sock->nr, state->Vcc, state->Vpp);
0289 v = p = 0;
0290 ret = -EINVAL;
0291 }
0292
0293
0294 if (sock->board_type != BOARD_TYPE_DB1300)
0295 cr_set |= ((v << 2) | p) << (sock->nr * 8);
0296
0297 changed = state->flags ^ sock->old_flags;
0298
0299 if (changed & SS_RESET) {
0300 if (state->flags & SS_RESET) {
0301 set_stschg(sock, 0);
0302
0303 cr_clr |= (1 << (7 + (sock->nr * 8)));
0304 cr_clr |= (1 << (4 + (sock->nr * 8)));
0305 } else {
0306
0307 cr_set |= 1 << (7 + (sock->nr * 8));
0308 cr_set |= 1 << (4 + (sock->nr * 8));
0309 }
0310 }
0311
0312
0313 bcsr_mod(BCSR_PCMCIA, cr_clr, cr_set);
0314
0315 sock->old_flags = state->flags;
0316
0317
0318 if ((changed & SS_RESET) && !(state->flags & SS_RESET)) {
0319 msleep(500);
0320 set_stschg(sock, 1);
0321 }
0322
0323 return ret;
0324 }
0325
0326
0327 #define GET_VCC(cr, socknr) \
0328 ((((cr) >> 2) >> ((socknr) * 8)) & 3)
0329
0330
0331 #define GET_VS(sr, socknr) \
0332 (((sr) >> (2 * (socknr))) & 3)
0333
0334
0335 #define GET_RESET(cr, socknr) \
0336 ((cr) & (1 << (7 + (8 * (socknr)))))
0337
0338 static int db1x_pcmcia_get_status(struct pcmcia_socket *skt,
0339 unsigned int *value)
0340 {
0341 struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);
0342 unsigned short cr, sr;
0343 unsigned int status;
0344
0345 status = db1x_card_inserted(sock) ? SS_DETECT : 0;
0346
0347 cr = bcsr_read(BCSR_PCMCIA);
0348 sr = bcsr_read(BCSR_STATUS);
0349
0350
0351 if (sock->board_type == BOARD_TYPE_PB1100)
0352 sr >>= 4;
0353
0354
0355 switch (GET_VS(sr, sock->nr)) {
0356 case 0:
0357 case 2:
0358 status |= SS_3VCARD;
0359 break;
0360 case 3:
0361 break;
0362 default:
0363 status |= SS_XVCARD;
0364 }
0365
0366
0367 status |= GET_VCC(cr, sock->nr) ? SS_POWERON : 0;
0368
0369
0370 if ((sock->board_type == BOARD_TYPE_DB1300) && (status & SS_DETECT))
0371 status = SS_POWERON | SS_3VCARD | SS_DETECT;
0372
0373
0374 status |= (GET_RESET(cr, sock->nr)) ? SS_READY : SS_RESET;
0375
0376 *value = status;
0377
0378 return 0;
0379 }
0380
0381 static int db1x_pcmcia_sock_init(struct pcmcia_socket *skt)
0382 {
0383 return 0;
0384 }
0385
0386 static int db1x_pcmcia_sock_suspend(struct pcmcia_socket *skt)
0387 {
0388 return 0;
0389 }
0390
0391 static int au1x00_pcmcia_set_io_map(struct pcmcia_socket *skt,
0392 struct pccard_io_map *map)
0393 {
0394 struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);
0395
0396 map->start = (u32)sock->virt_io;
0397 map->stop = map->start + IO_MAP_SIZE;
0398
0399 return 0;
0400 }
0401
0402 static int au1x00_pcmcia_set_mem_map(struct pcmcia_socket *skt,
0403 struct pccard_mem_map *map)
0404 {
0405 struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);
0406
0407 if (map->flags & MAP_ATTRIB)
0408 map->static_start = sock->phys_attr + map->card_start;
0409 else
0410 map->static_start = sock->phys_mem + map->card_start;
0411
0412 return 0;
0413 }
0414
0415 static struct pccard_operations db1x_pcmcia_operations = {
0416 .init = db1x_pcmcia_sock_init,
0417 .suspend = db1x_pcmcia_sock_suspend,
0418 .get_status = db1x_pcmcia_get_status,
0419 .set_socket = db1x_pcmcia_configure,
0420 .set_io_map = au1x00_pcmcia_set_io_map,
0421 .set_mem_map = au1x00_pcmcia_set_mem_map,
0422 };
0423
0424 static int db1x_pcmcia_socket_probe(struct platform_device *pdev)
0425 {
0426 struct db1x_pcmcia_sock *sock;
0427 struct resource *r;
0428 int ret, bid;
0429
0430 sock = kzalloc(sizeof(struct db1x_pcmcia_sock), GFP_KERNEL);
0431 if (!sock)
0432 return -ENOMEM;
0433
0434 sock->nr = pdev->id;
0435
0436 bid = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
0437 switch (bid) {
0438 case BCSR_WHOAMI_PB1500:
0439 case BCSR_WHOAMI_PB1500R2:
0440 case BCSR_WHOAMI_PB1100:
0441 sock->board_type = BOARD_TYPE_PB1100;
0442 break;
0443 case BCSR_WHOAMI_DB1000 ... BCSR_WHOAMI_PB1550_SDR:
0444 sock->board_type = BOARD_TYPE_DEFAULT;
0445 break;
0446 case BCSR_WHOAMI_PB1200 ... BCSR_WHOAMI_DB1200:
0447 sock->board_type = BOARD_TYPE_DB1200;
0448 break;
0449 case BCSR_WHOAMI_DB1300:
0450 sock->board_type = BOARD_TYPE_DB1300;
0451 break;
0452 default:
0453 printk(KERN_INFO "db1xxx-ss: unknown board %d!\n", bid);
0454 ret = -ENODEV;
0455 goto out0;
0456 }
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469 r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "card");
0470 sock->card_irq = r ? r->start : 0;
0471
0472
0473
0474
0475 r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "insert");
0476 sock->insert_irq = r ? r->start : -1;
0477 if (sock->board_type == BOARD_TYPE_DEFAULT) {
0478 sock->insert_gpio = r ? r->start : -1;
0479 sock->insert_irq = r ? gpio_to_irq(r->start) : -1;
0480 }
0481
0482
0483 r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "stschg");
0484 sock->stschg_irq = r ? r->start : -1;
0485
0486
0487 r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "eject");
0488 sock->eject_irq = r ? r->start : -1;
0489
0490 ret = -ENODEV;
0491
0492
0493 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");
0494 if (!r) {
0495 printk(KERN_ERR "pcmcia%d has no 'pseudo-attr' resource!\n",
0496 sock->nr);
0497 goto out0;
0498 }
0499 sock->phys_attr = r->start;
0500
0501
0502 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
0503 if (!r) {
0504 printk(KERN_ERR "pcmcia%d has no 'pseudo-mem' resource!\n",
0505 sock->nr);
0506 goto out0;
0507 }
0508 sock->phys_mem = r->start;
0509
0510
0511 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");
0512 if (!r) {
0513 printk(KERN_ERR "pcmcia%d has no 'pseudo-io' resource!\n",
0514 sock->nr);
0515 goto out0;
0516 }
0517 sock->phys_io = r->start;
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527 sock->virt_io = (void *)(ioremap(sock->phys_io, IO_MAP_SIZE) -
0528 mips_io_port_base);
0529
0530 if (!sock->virt_io) {
0531 printk(KERN_ERR "pcmcia%d: cannot remap IO area\n",
0532 sock->nr);
0533 ret = -ENOMEM;
0534 goto out0;
0535 }
0536
0537 sock->socket.ops = &db1x_pcmcia_operations;
0538 sock->socket.owner = THIS_MODULE;
0539 sock->socket.pci_irq = sock->card_irq;
0540 sock->socket.features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
0541 sock->socket.map_size = MEM_MAP_SIZE;
0542 sock->socket.io_offset = (unsigned long)sock->virt_io;
0543 sock->socket.dev.parent = &pdev->dev;
0544 sock->socket.resource_ops = &pccard_static_ops;
0545
0546 platform_set_drvdata(pdev, sock);
0547
0548 ret = db1x_pcmcia_setup_irqs(sock);
0549 if (ret) {
0550 printk(KERN_ERR "pcmcia%d cannot setup interrupts\n",
0551 sock->nr);
0552 goto out1;
0553 }
0554
0555 set_stschg(sock, 0);
0556
0557 ret = pcmcia_register_socket(&sock->socket);
0558 if (ret) {
0559 printk(KERN_ERR "pcmcia%d failed to register\n", sock->nr);
0560 goto out2;
0561 }
0562
0563 printk(KERN_INFO "Alchemy Db/Pb1xxx pcmcia%d @ io/attr/mem %09llx"
0564 "(%p) %09llx %09llx card/insert/stschg/eject irqs @ %d "
0565 "%d %d %d\n", sock->nr, sock->phys_io, sock->virt_io,
0566 sock->phys_attr, sock->phys_mem, sock->card_irq,
0567 sock->insert_irq, sock->stschg_irq, sock->eject_irq);
0568
0569 return 0;
0570
0571 out2:
0572 db1x_pcmcia_free_irqs(sock);
0573 out1:
0574 iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
0575 out0:
0576 kfree(sock);
0577 return ret;
0578 }
0579
0580 static int db1x_pcmcia_socket_remove(struct platform_device *pdev)
0581 {
0582 struct db1x_pcmcia_sock *sock = platform_get_drvdata(pdev);
0583
0584 db1x_pcmcia_free_irqs(sock);
0585 pcmcia_unregister_socket(&sock->socket);
0586 iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
0587 kfree(sock);
0588
0589 return 0;
0590 }
0591
0592 static struct platform_driver db1x_pcmcia_socket_driver = {
0593 .driver = {
0594 .name = "db1xxx_pcmcia",
0595 },
0596 .probe = db1x_pcmcia_socket_probe,
0597 .remove = db1x_pcmcia_socket_remove,
0598 };
0599
0600 module_platform_driver(db1x_pcmcia_socket_driver);
0601
0602 MODULE_LICENSE("GPL");
0603 MODULE_DESCRIPTION("PCMCIA Socket Services for Alchemy Db/Pb1x00 boards");
0604 MODULE_AUTHOR("Manuel Lauss");