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_get_status(u_short sock, u_int *value) { u_int status; pr_debug("m32r_cfc: _pcc_get_status:\n"); status = pcc_get(sock, (unsigned int)PLD_CFSTS); *value = (status) ? SS_DETECT : 0; pr_debug("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)) { pr_debug("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); pr_debug("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); pr_debug("m32r_cfc: _pcc_get_status: " "power off (CPCR=0x%08x)\n", status); } #else #error no platform configuration #endif pr_debug("m32r_cfc: _pcc_get_status: GetStatus(%d) = %#4.4x\n", sock, *value); return 0; } /* _get_status */
static void add_pcc_socket(ulong base, int irq, ulong mapaddr, unsigned int ioaddr) { pcc_socket_t *t = &socket[pcc_sockets]; pr_debug("m32r_cfc: add_pcc_socket: base=%#lx, irq=%d, " "mapaddr=%#lx, ioaddr=%08x\n", base, irq, mapaddr, ioaddr); /* add sockets */ t->ioaddr = ioaddr; t->mapaddr = mapaddr; #if !defined(CONFIG_PLAT_USRV) t->base = 0; t->flags = 0; t->cs_irq1 = irq; // insert irq t->cs_irq2 = irq + 1; // eject irq #else /* CONFIG_PLAT_USRV */ t->base = base; t->flags = 0; t->cs_irq1 = 0; // insert irq t->cs_irq2 = 0; // eject irq #endif /* CONFIG_PLAT_USRV */ if (is_alive(pcc_sockets)) t->flags |= IS_ALIVE; /* add pcc */ #if !defined(CONFIG_PLAT_USRV) request_region((unsigned int)PLD_CFRSTCR, 0x20, "m32r_cfc"); #else /* CONFIG_PLAT_USRV */ { unsigned int reg_base; reg_base = (unsigned int)PLD_CFRSTCR; reg_base |= pcc_sockets << 8; request_region(reg_base, 0x20, "m32r_cfc"); } #endif /* CONFIG_PLAT_USRV */ printk(KERN_INFO " %s ", pcc[pcc_sockets].name); printk("pcc at 0x%08lx\n", t->base); /* Update socket interrupt information, capabilities */ t->socket.features |= (SS_CAP_PCCARD | SS_CAP_STATIC_MAP); t->socket.map_size = M32R_PCC_MAPSIZE; t->socket.io_offset = ioaddr; /* use for io access offset */ t->socket.irq_mask = 0; #if !defined(CONFIG_PLAT_USRV) t->socket.pci_irq = PLD_IRQ_CFIREQ ; /* card interrupt */ #else /* CONFIG_PLAT_USRV */ t->socket.pci_irq = PLD_IRQ_CF0 + pcc_sockets; #endif /* CONFIG_PLAT_USRV */ #ifndef CONFIG_PLAT_USRV /* insert interrupt */ request_irq(irq, pcc_interrupt, 0, "m32r_cfc", pcc_interrupt); #ifndef CONFIG_PLAT_MAPPI3 /* eject interrupt */ request_irq(irq+1, pcc_interrupt, 0, "m32r_cfc", pcc_interrupt); #endif pr_debug("m32r_cfc: enable CFMSK, RDYSEL\n"); pcc_set(pcc_sockets, (unsigned int)PLD_CFIMASK, 0x01); #endif /* CONFIG_PLAT_USRV */ #if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) pcc_set(pcc_sockets, (unsigned int)PLD_CFCR1, 0x0200); #endif pcc_sockets++; return; }
static int __init init_m32r_pcc(void) { int i, ret; ret = platform_driver_register(&pcc_driver); if (ret) return ret; ret = platform_device_register(&pcc_device); if (ret){ platform_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; unsigned int 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); platform_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_static_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; } /* 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 */