m32r_cfc.c
来自「linux 内核源代码」· C语言 代码 · 共 811 行 · 第 1/2 页
C
811 行
static int _pcc_get_status(u_short sock, u_int *value){ u_int status; debug(3, "m32r_cfc: _pcc_get_status:\n"); status = pcc_get(sock, (unsigned int)PLD_CFSTS); *value = (status) ? SS_DETECT : 0; debug(3, "m32r_cfc: _pcc_get_status: status=0x%08x\n", status);#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) if ( status ) { /* enable CF power */ status = inw((unsigned int)PLD_CPCR); if (!(status & PLD_CPCR_CF)) { debug(3, "m32r_cfc: _pcc_get_status: " "power on (CPCR=0x%08x)\n", status); status |= PLD_CPCR_CF; outw(status, (unsigned int)PLD_CPCR); udelay(100); } *value |= SS_POWERON; pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);/* enable buffer */ udelay(100); *value |= SS_READY; /* always ready */ *value |= SS_3VCARD; } else { /* disable CF power */ status = inw((unsigned int)PLD_CPCR); status &= ~PLD_CPCR_CF; outw(status, (unsigned int)PLD_CPCR); udelay(100); debug(3, "m32r_cfc: _pcc_get_status: " "power off (CPCR=0x%08x)\n", status); }#elif defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3) if ( status ) { status = pcc_get(sock, (unsigned int)PLD_CPCR); if (status == 0) { /* power off */ pcc_set(sock, (unsigned int)PLD_CPCR, 1); pcc_set(sock, (unsigned int)PLD_CFBUFCR,0); /* force buffer off for ZA-36 */ udelay(50); } *value |= SS_POWERON; pcc_set(sock, (unsigned int)PLD_CFBUFCR,0); udelay(50); pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0101); udelay(25); /* for IDE reset */ pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0100); mdelay(2); /* for IDE reset */ *value |= SS_READY; *value |= SS_3VCARD; } else { /* disable CF power */ pcc_set(sock, (unsigned int)PLD_CPCR, 0); udelay(100); debug(3, "m32r_cfc: _pcc_get_status: " "power off (CPCR=0x%08x)\n", status); }#else#error no platform configuration#endif debug(3, "m32r_cfc: _pcc_get_status: GetStatus(%d) = %#4.4x\n", sock, *value); return 0;} /* _get_status *//*====================================================================*/static int _pcc_set_socket(u_short sock, socket_state_t *state){ debug(3, "m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags, state->Vcc, state->Vpp, state->io_irq, state->csc_mask);#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3) if (state->Vcc) { if ((state->Vcc != 50) && (state->Vcc != 33)) return -EINVAL; /* accept 5V and 3.3V */ }#endif if (state->flags & SS_RESET) { debug(3, ":RESET\n"); pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x101); }else{ pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x100); } if (state->flags & SS_OUTPUT_ENA){ debug(3, ":OUTPUT_ENA\n"); /* bit clear */ pcc_set(sock,(unsigned int)PLD_CFBUFCR,0); } else { pcc_set(sock,(unsigned int)PLD_CFBUFCR,1); }#ifdef DEBUG if(state->flags & SS_IOCARD){ debug(3, ":IOCARD"); } if (state->flags & SS_PWR_AUTO) { debug(3, ":PWR_AUTO"); } if (state->csc_mask & SS_DETECT) debug(3, ":csc-SS_DETECT"); if (state->flags & SS_IOCARD) { if (state->csc_mask & SS_STSCHG) debug(3, ":STSCHG"); } else { if (state->csc_mask & SS_BATDEAD) debug(3, ":BATDEAD"); if (state->csc_mask & SS_BATWARN) debug(3, ":BATWARN"); if (state->csc_mask & SS_READY) debug(3, ":READY"); } debug(3, "\n");#endif return 0;} /* _set_socket *//*====================================================================*/static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io){ u_char map; debug(3, "m32r_cfc: SetIOMap(%d, %d, %#2.2x, %d ns, " "%#lx-%#lx)\n", sock, io->map, io->flags, io->speed, io->start, io->stop); map = io->map; return 0;} /* _set_io_map *//*====================================================================*/static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem){ u_char map = mem->map; u_long addr; pcc_socket_t *t = &socket[sock]; debug(3, "m32r_cfc: SetMemMap(%d, %d, %#2.2x, %d ns, " "%#lx, %#x)\n", sock, map, mem->flags, mem->speed, mem->static_start, mem->card_start); /* * sanity check */ if ((map > MAX_WIN) || (mem->card_start > 0x3ffffff)){ return -EINVAL; } /* * de-activate */ if ((mem->flags & MAP_ACTIVE) == 0) { t->current_space = as_none; return 0; } /* * Set mode */ if (mem->flags & MAP_ATTRIB) { t->current_space = as_attr; } else { t->current_space = as_comm; } /* * Set address */ addr = t->mapaddr + (mem->card_start & M32R_PCC_MAPMASK); mem->static_start = addr + mem->card_start; return 0;} /* _set_mem_map */#if 0 /* driver model ordering issue *//*====================================================================== Routines for accessing socket information and register dumps via /proc/bus/pccard/...======================================================================*/static ssize_t show_info(struct class_device *class_dev, char *buf){ pcc_socket_t *s = container_of(class_dev, struct pcc_socket, socket.dev); return sprintf(buf, "type: %s\nbase addr: 0x%08lx\n", pcc[s->type].name, s->base);}static ssize_t show_exca(struct class_device *class_dev, char *buf){ /* FIXME */ return 0;}static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL);static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL);#endif/*====================================================================*//* this is horribly ugly... proper locking needs to be done here at * some time... */#define LOCKED(x) do { \ int retval; \ unsigned long flags; \ spin_lock_irqsave(&pcc_lock, flags); \ retval = x; \ spin_unlock_irqrestore(&pcc_lock, flags); \ return retval; \} while (0)static int pcc_get_status(struct pcmcia_socket *s, u_int *value){ unsigned int sock = container_of(s, struct pcc_socket, socket)->number; if (socket[sock].flags & IS_ALIVE) { debug(3, "m32r_cfc: pcc_get_status: sock(%d) -EINVAL\n", sock); *value = 0; return -EINVAL; } debug(3, "m32r_cfc: pcc_get_status: sock(%d)\n", sock); LOCKED(_pcc_get_status(sock, value));}static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state){ unsigned int sock = container_of(s, struct pcc_socket, socket)->number; if (socket[sock].flags & IS_ALIVE) { debug(3, "m32r_cfc: pcc_set_socket: sock(%d) -EINVAL\n", sock); return -EINVAL; } debug(3, "m32r_cfc: pcc_set_socket: sock(%d)\n", sock); LOCKED(_pcc_set_socket(sock, state));}static int pcc_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io){ unsigned int sock = container_of(s, struct pcc_socket, socket)->number; if (socket[sock].flags & IS_ALIVE) { debug(3, "m32r_cfc: pcc_set_io_map: sock(%d) -EINVAL\n", sock); return -EINVAL; } debug(3, "m32r_cfc: pcc_set_io_map: sock(%d)\n", sock); LOCKED(_pcc_set_io_map(sock, io));}static int pcc_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem){ unsigned int sock = container_of(s, struct pcc_socket, socket)->number; if (socket[sock].flags & IS_ALIVE) { debug(3, "m32r_cfc: pcc_set_mem_map: sock(%d) -EINVAL\n", sock); return -EINVAL; } debug(3, "m32r_cfc: pcc_set_mem_map: sock(%d)\n", sock); LOCKED(_pcc_set_mem_map(sock, mem));}static int pcc_init(struct pcmcia_socket *s){ debug(3, "m32r_cfc: pcc_init()\n"); return 0;}static struct pccard_operations pcc_operations = { .init = pcc_init, .get_status = pcc_get_status, .set_socket = pcc_set_socket, .set_io_map = pcc_set_io_map, .set_mem_map = pcc_set_mem_map,};/*====================================================================*/static struct device_driver pcc_driver = { .name = "cfc", .bus = &platform_bus_type, .suspend = pcmcia_socket_dev_suspend, .resume = pcmcia_socket_dev_resume,};static struct platform_device pcc_device = { .name = "cfc", .id = 0,};/*====================================================================*/static int __init init_m32r_pcc(void){ int i, ret; ret = driver_register(&pcc_driver); if (ret) return ret; ret = platform_device_register(&pcc_device); if (ret){ driver_unregister(&pcc_driver); return ret; }#if defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3) pcc_set(0, (unsigned int)PLD_CFCR0, 0x0f0f); pcc_set(0, (unsigned int)PLD_CFCR1, 0x0200);#endif pcc_sockets = 0;#if !defined(CONFIG_PLAT_USRV) add_pcc_socket(M32R_PCC0_BASE, PLD_IRQ_CFC_INSERT, CFC_ATTR_MAPBASE, CFC_IOPORT_BASE);#else /* CONFIG_PLAT_USRV */ { ulong base, mapaddr; kio_addr_t ioaddr; for (i = 0 ; i < M32R_MAX_PCC ; i++) { base = (ulong)PLD_CFRSTCR; base = base | (i << 8); ioaddr = (i + 1) << 12; mapaddr = CFC_ATTR_MAPBASE | (i << 20); add_pcc_socket(base, 0, mapaddr, ioaddr); } }#endif /* CONFIG_PLAT_USRV */ if (pcc_sockets == 0) { printk("socket is not found.\n"); platform_device_unregister(&pcc_device); driver_unregister(&pcc_driver); return -ENODEV; } /* Set up interrupt handler(s) */ for (i = 0 ; i < pcc_sockets ; i++) { socket[i].socket.dev.parent = &pcc_device.dev; socket[i].socket.ops = &pcc_operations; socket[i].socket.resource_ops = &pccard_nonstatic_ops; socket[i].socket.owner = THIS_MODULE; socket[i].number = i; ret = pcmcia_register_socket(&socket[i].socket); if (!ret) socket[i].flags |= IS_REGISTERED;#if 0 /* driver model ordering issue */ class_device_create_file(&socket[i].socket.dev, &class_device_attr_info); class_device_create_file(&socket[i].socket.dev, &class_device_attr_exca);#endif } /* Finally, schedule a polling interrupt */ if (poll_interval != 0) { poll_timer.function = pcc_interrupt_wrapper; poll_timer.data = 0; init_timer(&poll_timer); poll_timer.expires = jiffies + poll_interval; add_timer(&poll_timer); } return 0;} /* init_m32r_pcc */static void __exit exit_m32r_pcc(void){ int i; for (i = 0; i < pcc_sockets; i++) if (socket[i].flags & IS_REGISTERED) pcmcia_unregister_socket(&socket[i].socket); platform_device_unregister(&pcc_device); if (poll_interval != 0) del_timer_sync(&poll_timer); driver_unregister(&pcc_driver);} /* exit_m32r_pcc */module_init(init_m32r_pcc);module_exit(exit_m32r_pcc);MODULE_LICENSE("Dual MPL/GPL");/*====================================================================*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?