static int jornada720_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { /* * What is all this crap for? */ GRER |= 0x00000002; /* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */ sa1111_set_io_dir(SA1111_DEV(skt->dev), GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0); sa1111_set_io(SA1111_DEV(skt->dev), GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); sa1111_set_sleep_io(SA1111_DEV(skt->dev), GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); return sa1111_pcmcia_hw_init(skt); }
void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { struct sa1111_dev *sadev = SA1111_DEV(skt->dev); unsigned long status = sa1111_readl(sadev->mapbase + SA1111_PCSR); switch (skt->nr) { case 0: state->detect = status & PCSR_S0_DETECT ? 0 : 1; state->ready = status & PCSR_S0_READY ? 1 : 0; state->bvd1 = status & PCSR_S0_BVD1 ? 1 : 0; state->bvd2 = status & PCSR_S0_BVD2 ? 1 : 0; state->wrprot = status & PCSR_S0_WP ? 1 : 0; state->vs_3v = status & PCSR_S0_VS1 ? 0 : 1; state->vs_Xv = status & PCSR_S0_VS2 ? 0 : 1; break; case 1: state->detect = status & PCSR_S1_DETECT ? 0 : 1; state->ready = status & PCSR_S1_READY ? 1 : 0; state->bvd1 = status & PCSR_S1_BVD1 ? 1 : 0; state->bvd2 = status & PCSR_S1_BVD2 ? 1 : 0; state->wrprot = status & PCSR_S1_WP ? 1 : 0; state->vs_3v = status & PCSR_S1_VS1 ? 0 : 1; state->vs_Xv = status & PCSR_S1_VS2 ? 0 : 1; break; } }
static int jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { unsigned int pa_dwr_mask, pa_dwr_set; int ret; printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__, skt->nr, state->Vcc, state->Vpp); switch (skt->nr) { case 0: pa_dwr_mask = SOCKET0_POWER | SOCKET0_3V; switch (state->Vcc) { default: case 0: pa_dwr_set = 0; break; case 33: pa_dwr_set = SOCKET0_POWER | SOCKET0_3V; break; case 50: pa_dwr_set = SOCKET0_POWER; break; } break; case 1: pa_dwr_mask = SOCKET1_POWER; switch (state->Vcc) { default: case 0: pa_dwr_set = 0; break; case 33: pa_dwr_set = SOCKET1_POWER; break; case 50: pa_dwr_set = SOCKET1_POWER; break; } break; default: return -1; } if (state->Vpp != state->Vcc && state->Vpp != 0) { printk(KERN_ERR "%s(): slot cannot support VPP %u\n", __FUNCTION__, state->Vpp); return -1; } ret = sa1111_pcmcia_configure_socket(skt, state); if (ret == 0) { unsigned long flags; local_irq_save(flags); sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set); local_irq_restore(flags); } return ret; }
int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { struct sa1111_dev *sadev = SA1111_DEV(skt->dev); unsigned int pccr_skt_mask, pccr_set_mask, val; unsigned long flags; switch (skt->nr) { case 0: pccr_skt_mask = PCCR_S0_RST|PCCR_S0_FLT|PCCR_S0_PWAITEN|PCCR_S0_PSE; break; case 1: pccr_skt_mask = PCCR_S1_RST|PCCR_S1_FLT|PCCR_S1_PWAITEN|PCCR_S1_PSE; break; default: return -1; } pccr_set_mask = 0; if (state->Vcc != 0) pccr_set_mask |= PCCR_S0_PWAITEN|PCCR_S1_PWAITEN; if (state->Vcc == 50) pccr_set_mask |= PCCR_S0_PSE|PCCR_S1_PSE; if (state->flags & SS_RESET) pccr_set_mask |= PCCR_S0_RST|PCCR_S1_RST; if (state->flags & SS_OUTPUT_ENA) pccr_set_mask |= PCCR_S0_FLT|PCCR_S1_FLT; local_irq_save(flags); val = sa1111_readl(sadev->mapbase + SA1111_PCCR); val &= ~pccr_skt_mask; val |= pccr_set_mask & pccr_skt_mask; sa1111_writel(val, sadev->mapbase + SA1111_PCCR); local_irq_restore(flags); return 0; }
static int lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set; int ret = 0; pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0; again: switch (skt->nr) { case 0: pa_dwr_mask = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3; switch (state->Vcc) { case 0: break; case 33: pa_dwr_set |= GPIO_A3; break; case 50: pa_dwr_set |= GPIO_A2; break; default: printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __func__, state->Vcc); ret = -1; } switch (state->Vpp) { case 0: break; case 120: pa_dwr_set |= GPIO_A1; break; default: if (state->Vpp == state->Vcc) pa_dwr_set |= GPIO_A0; else { printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __func__, state->Vpp); ret = -1; break; } } break; case 1: misc_mask = (1 << 15) | (1 << 14); switch (state->Vcc) { case 0: break; case 33: misc_set |= 1 << 15; break; case 50: misc_set |= 1 << 14; break; default: printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __func__, state->Vcc); ret = -1; break; } if (state->Vpp != state->Vcc && state->Vpp != 0) { printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __func__, state->Vpp); ret = -1; break; } break; default: ret = -1; } if (ret == 0) ret = sa1111_pcmcia_configure_socket(skt, state); if (ret == 0) { lubbock_set_misc_wr(misc_mask, misc_set); sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set); } #if 1 if (ret == 0 && state->Vcc == 33) { struct pcmcia_state new_state; mdelay(3); sa1111_pcmcia_socket_state(skt, &new_state); if (!new_state.vs_3v && !new_state.vs_Xv) { lubbock_set_misc_wr(misc_mask, 0); sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, 0); mdelay(100); ((socket_state_t *)state)->Vcc = 50; ((socket_state_t *)state)->Vpp = 50; goto again; } } #endif return ret; }
static int neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { unsigned int ncr_mask, ncr_set, pa_dwr_mask, pa_dwr_set; int ret; switch (skt->nr) { case 0: pa_dwr_mask = GPIO_A0 | GPIO_A1; ncr_mask = NCR_A0VPP | NCR_A1VPP; if (state->Vpp == 0) ncr_set = 0; else if (state->Vpp == 120) ncr_set = NCR_A1VPP; else if (state->Vpp == state->Vcc) ncr_set = NCR_A0VPP; else { printk(KERN_ERR "%s(): unrecognized VPP %u\n", __func__, state->Vpp); return -1; } break; case 1: pa_dwr_mask = GPIO_A2 | GPIO_A3; ncr_mask = 0; ncr_set = 0; if (state->Vpp != state->Vcc && state->Vpp != 0) { printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n", __func__, state->Vpp); return -1; } break; default: return -1; } /* * pa_dwr_set is the mask for selecting Vcc on both sockets. * pa_dwr_mask selects which bits (and therefore socket) we change. */ switch (state->Vcc) { default: case 0: pa_dwr_set = 0; break; case 33: pa_dwr_set = GPIO_A1|GPIO_A2; break; case 50: pa_dwr_set = GPIO_A0|GPIO_A3; break; } ret = sa1111_pcmcia_configure_socket(skt, state); if (ret == 0) { unsigned long flags; local_irq_save(flags); NCR_0 = (NCR_0 & ~ncr_mask) | ncr_set; local_irq_restore(flags); sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set); } return 0; }
static int lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set; int ret = 0; pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0; /* Lubbock uses the Maxim MAX1602, with the following connections: * * Socket 0 (PCMCIA): * MAX1602 Lubbock Register * Pin Signal * ----- ------- ---------------------- * A0VPP S0_PWR0 SA-1111 GPIO A<0> * A1VPP S0_PWR1 SA-1111 GPIO A<1> * A0VCC S0_PWR2 SA-1111 GPIO A<2> * A1VCC S0_PWR3 SA-1111 GPIO A<3> * VX VCC * VY +3.3V * 12IN +12V * CODE +3.3V Cirrus Code, CODE = High (VY) * * Socket 1 (CF): * MAX1602 Lubbock Register * Pin Signal * ----- ------- ---------------------- * A0VPP GND VPP is not connected * A1VPP GND VPP is not connected * A0VCC S1_PWR0 MISC_WR<14> * A1VCC S1_PWR1 MISC_WR<15> * VX VCC * VY +3.3V * 12IN GND VPP is not connected * CODE +3.3V Cirrus Code, CODE = High (VY) * */ again: switch (skt->nr) { case 0: pa_dwr_mask = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3; switch (state->Vcc) { case 0: /* Hi-Z */ break; case 33: /* VY */ pa_dwr_set |= GPIO_A3; break; case 50: /* VX */ pa_dwr_set |= GPIO_A2; break; default: printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc); ret = -1; } switch (state->Vpp) { case 0: /* Hi-Z */ break; case 120: /* 12IN */ pa_dwr_set |= GPIO_A1; break; default: /* VCC */ if (state->Vpp == state->Vcc) pa_dwr_set |= GPIO_A0; else { printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__, state->Vpp); ret = -1; break; } } break; case 1: misc_mask = (1 << 15) | (1 << 14); switch (state->Vcc) { case 0: /* Hi-Z */ break; case 33: /* VY */ misc_set |= 1 << 15; break; case 50: /* VX */ misc_set |= 1 << 14; break; default: printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc); ret = -1; break; } if (state->Vpp != state->Vcc && state->Vpp != 0) { printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__, state->Vpp); ret = -1; break; } break; default: ret = -1; } if (ret == 0) ret = sa1111_pcmcia_configure_socket(skt, state); if (ret == 0) { lubbock_set_misc_wr(misc_mask, misc_set); sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set); } #if 1 if (ret == 0 && state->Vcc == 33) { struct pcmcia_state new_state; /* * HACK ALERT: * We can't sense the voltage properly on Lubbock before * actually applying some power to the socket (catch 22). * Resense the socket Voltage Sense pins after applying * socket power. * * Note: It takes about 2.5ms for the MAX1602 VCC output * to rise. */ mdelay(3); sa1111_pcmcia_socket_state(skt, &new_state); if (!new_state.vs_3v && !new_state.vs_Xv) { /* * Switch to 5V, Configure socket with 5V voltage */ lubbock_set_misc_wr(misc_mask, 0); sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, 0); /* * It takes about 100ms to turn off Vcc. */ mdelay(100); /* * We need to hack around the const qualifier as * well to keep this ugly workaround localized and * not force it to the rest of the code. Barf bags * avaliable in the seat pocket in front of you! */ ((socket_state_t *)state)->Vcc = 50; ((socket_state_t *)state)->Vpp = 50; goto again; } } #endif return ret; }