/* sa1100_pcmcia_set_io_map() * ^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the set_io_map() operation for the in-kernel PCMCIA * service (formerly SS_SetIOMap in Card Services). We configure * the map speed as requested, but override the address ranges * supplied by Card Services. * * Returns: 0 on success, -1 on error */ static int sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map) { struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock); DEBUG(3, "\tmap %u speed %u\n\tstart 0x%08x stop 0x%08x\n", map->map, map->speed, map->start, map->stop); DEBUG(3, "\tflags: %s%s%s%s%s%s%s%s\n", (map->flags==0)?"<NONE>":"", (map->flags&MAP_ACTIVE)?"ACTIVE ":"", (map->flags&MAP_16BIT)?"16BIT ":"", (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"", (map->flags&MAP_0WS)?"0WS ":"", (map->flags&MAP_WRPROT)?"WRPROT ":"", (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"", (map->flags&MAP_PREFETCH)?"PREFETCH ":""); if (map->map >= MAX_IO_WIN) { printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__, map->map); return -1; } if (map->flags & MAP_ACTIVE) { unsigned int clock, speed = map->speed; unsigned long mecr; if (speed == 0) speed = SA1100_PCMCIA_IO_ACCESS; clock = cpufreq_get(0); mecr = MECR; MECR_BSIO_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock)); skt->speed_io = speed; DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n", __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock, MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), sock, MECR_BSIO_GET(mecr, sock)); MECR = mecr; } if (map->stop == 1) map->stop = PAGE_SIZE-1; map->stop -= map->start; map->stop += (unsigned long)skt->virt_io; map->start = (unsigned long)skt->virt_io; skt->io_map[map->map] = *map; return 0; } /* sa1100_pcmcia_set_io_map() */
/* pxa_pcmcia_set_mem_map() * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the set_mem_map() operation for the in-kernel PCMCIA * service (formerly SS_SetMemMap in Card Services). We configure * the map speed as requested, but override the address ranges * supplied by Card Services. * * Returns: 0 on success, -1 on error */ static int pxa_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map){ unsigned int clock, speed; unsigned long mecr, start; DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock); DEBUG(4, "\tmap %u speed %u\n\tsys_start %#lx\n" "\tsys_stop %#lx\n\tcard_start %#x\n" "\tflags: %s%s%s%s%s%s%s%s\n", map->map, map->speed, map->sys_start, map->sys_stop, map->card_start, (map->flags==0)?"<NONE>":"", (map->flags&MAP_ACTIVE)?"ACTIVE ":"", (map->flags&MAP_16BIT)?"16BIT ":"", (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"", (map->flags&MAP_0WS)?"0WS ":"", (map->flags&MAP_WRPROT)?"WRPROT ":"", (map->flags&MAP_ATTRIB)?"ATTRIB ":"", (map->flags&MAP_USE_WAIT)?"USE_WAIT ":""); if(map->map>=MAX_WIN){ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__, map->map); return -1; } if(map->flags&MAP_ACTIVE){ /* When clients issue RequestMap, the access speed is not always * properly configured: */ if(map->speed > 0) speed = map->speed; else switch(pxa_pcmcia_socket[sock].cs_state.Vcc){ case 33: speed = PXA_PCMCIA_3V_MEM_ACCESS; break; default: speed = PXA_PCMCIA_5V_MEM_ACCESS; } clock = get_lclk_frequency_10khz(); if(map->flags&MAP_ATTRIB){ if (sock == 0) { MCATT0 = ((pxa_mcxx_setup(speed, clock) & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) | ((pxa_mcxx_asst(speed, clock) & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) | ((pxa_mcxx_hold(speed, clock) & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); } else { MCATT1 = ((pxa_mcxx_setup(speed, clock) & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) | ((pxa_mcxx_asst(speed, clock) & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) | ((pxa_mcxx_hold(speed, clock) & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); } pxa_pcmcia_socket[sock].speed_attr=speed; } else { if (sock == 0) { MCMEM0 = ((pxa_mcxx_setup(speed, clock) & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) | ((pxa_mcxx_asst(speed, clock) & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) | ((pxa_mcxx_hold(speed, clock) & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); } else { MCMEM1 = ((pxa_mcxx_setup(speed, clock) & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) | ((pxa_mcxx_asst(speed, clock) & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) | ((pxa_mcxx_hold(speed, clock) & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); } pxa_pcmcia_socket[sock].speed_mem=speed; } DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n", __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock, MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), sock, MECR_BSIO_GET(mecr, sock)); } start=map->sys_start; if(map->sys_stop==0) map->sys_stop=PAGE_SIZE-1; map->sys_start=(map->flags & MAP_ATTRIB)?\ pxa_pcmcia_socket[sock].phys_attr:\ pxa_pcmcia_socket[sock].phys_mem; map->sys_stop=map->sys_start+(map->sys_stop-start); pxa_pcmcia_socket[sock].mem_map[map->map]=*map; return 0; } /* pxa_pcmcia_set_mem_map() */
/* pxa_pcmcia_set_io_map() * ^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the set_io_map() operation for the in-kernel PCMCIA * service (formerly SS_SetIOMap in Card Services). We configure * the map speed as requested, but override the address ranges * supplied by Card Services. * * Returns: 0 on success, -1 on error */ static int pxa_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map){ unsigned int clock, speed; unsigned long mecr, start; DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock); DEBUG(4, "\tmap %u speed %u\n\tstart 0x%08lx stop 0x%08lx\n" "\tflags: %s%s%s%s%s%s%s%s\n", map->map, map->speed, map->start, map->stop, (map->flags==0)?"<NONE>":"", (map->flags&MAP_ACTIVE)?"ACTIVE ":"", (map->flags&MAP_16BIT)?"16BIT ":"", (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"", (map->flags&MAP_0WS)?"0WS ":"", (map->flags&MAP_WRPROT)?"WRPROT ":"", (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"", (map->flags&MAP_PREFETCH)?"PREFETCH ":""); if(map->map>=MAX_IO_WIN){ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__, map->map); return -1; } if(map->flags&MAP_ACTIVE){ speed=(map->speed>0)?map->speed:PXA_PCMCIA_IO_ACCESS; clock = get_lclk_frequency_10khz(); pxa_pcmcia_socket[sock].speed_io=speed; if (sock == 0) { MCIO0 = ((pxa_mcxx_setup(speed, clock) & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) | ((pxa_mcxx_asst(speed, clock) & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) | ((pxa_mcxx_hold(speed, clock) & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); } else { MCIO1 = ((pxa_mcxx_setup(speed, clock) & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) | ((pxa_mcxx_asst(speed, clock) & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) | ((pxa_mcxx_hold(speed, clock) & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); } DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n", __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock, MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), sock, MECR_BSIO_GET(mecr, sock)); } start=map->start; if(map->stop==1) map->stop=PAGE_SIZE-1; map->start=pxa_pcmcia_socket[sock].virt_io; map->stop=map->start+(map->stop-start); pxa_pcmcia_socket[sock].io_map[map->map]=*map; return 0; } /* pxa_pcmcia_set_io_map() */
/* sa1100_pcmcia_proc_status() * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the /proc/bus/pccard/??/status file. * * Returns: the number of characters added to the buffer */ static int sa1100_pcmcia_proc_status(char *buf, char **start, off_t pos, int count, int *eof, void *data) { unsigned int sock = (unsigned int)data; unsigned int clock = cpufreq_get(0); struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); unsigned long mecr = MECR; char *p = buf; p+=sprintf(p, "k_state : %s%s%s%s%s%s%s\n", skt->k_state.detect ? "detect " : "", skt->k_state.ready ? "ready " : "", skt->k_state.bvd1 ? "bvd1 " : "", skt->k_state.bvd2 ? "bvd2 " : "", skt->k_state.wrprot ? "wrprot " : "", skt->k_state.vs_3v ? "vs_3v " : "", skt->k_state.vs_Xv ? "vs_Xv " : ""); p+=sprintf(p, "status : %s%s%s%s%s%s%s%s%s\n", skt->k_state.detect ? "SS_DETECT " : "", skt->k_state.ready ? "SS_READY " : "", skt->cs_state.Vcc ? "SS_POWERON " : "", skt->cs_state.flags & SS_IOCARD ? "SS_IOCARD " : "", (skt->cs_state.flags & SS_IOCARD && skt->k_state.bvd1) ? "SS_STSCHG " : "", ((skt->cs_state.flags & SS_IOCARD)==0 && (skt->k_state.bvd1==0)) ? "SS_BATDEAD " : "", ((skt->cs_state.flags & SS_IOCARD)==0 && (skt->k_state.bvd2==0)) ? "SS_BATWARN " : "", skt->k_state.vs_3v ? "SS_3VCARD " : "", skt->k_state.vs_Xv ? "SS_XVCARD " : ""); p+=sprintf(p, "mask : %s%s%s%s%s\n", skt->cs_state.csc_mask & SS_DETECT ? "SS_DETECT " : "", skt->cs_state.csc_mask & SS_READY ? "SS_READY " : "", skt->cs_state.csc_mask & SS_BATDEAD ? "SS_BATDEAD " : "", skt->cs_state.csc_mask & SS_BATWARN ? "SS_BATWARN " : "", skt->cs_state.csc_mask & SS_STSCHG ? "SS_STSCHG " : ""); p+=sprintf(p, "cs_flags : %s%s%s%s%s\n", skt->cs_state.flags & SS_PWR_AUTO ? "SS_PWR_AUTO " : "", skt->cs_state.flags & SS_IOCARD ? "SS_IOCARD " : "", skt->cs_state.flags & SS_RESET ? "SS_RESET " : "", skt->cs_state.flags & SS_SPKR_ENA ? "SS_SPKR_ENA " : "", skt->cs_state.flags & SS_OUTPUT_ENA ? "SS_OUTPUT_ENA " : ""); p+=sprintf(p, "Vcc : %d\n", skt->cs_state.Vcc); p+=sprintf(p, "Vpp : %d\n", skt->cs_state.Vpp); p+=sprintf(p, "IRQ : %d\n", skt->cs_state.io_irq); p+=sprintf(p, "I/O : %u (%u)\n", skt->speed_io, sa1100_pcmcia_cmd_time(clock, MECR_BSIO_GET(mecr, sock))); p+=sprintf(p, "attribute: %u (%u)\n", skt->speed_attr, sa1100_pcmcia_cmd_time(clock, MECR_BSA_GET(mecr, sock))); p+=sprintf(p, "common : %u (%u)\n", skt->speed_mem, sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, sock))); return p-buf; }
/* sa1100_pcmcia_set_mem_map() * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the set_mem_map() operation for the in-kernel PCMCIA * service (formerly SS_SetMemMap in Card Services). We configure * the map speed as requested, but override the address ranges * supplied by Card Services. * * Returns: 0 on success, -1 on error */ static int sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map) { struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); unsigned long start; DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock); DEBUG(3, "\tmap %u speed %u sys_start %08lx sys_stop %08lx card_start %08x\n", map->map, map->speed, map->sys_start, map->sys_stop, map->card_start); DEBUG(3, "\tflags: %s%s%s%s%s%s%s%s\n", (map->flags==0)?"<NONE>":"", (map->flags&MAP_ACTIVE)?"ACTIVE ":"", (map->flags&MAP_16BIT)?"16BIT ":"", (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"", (map->flags&MAP_0WS)?"0WS ":"", (map->flags&MAP_WRPROT)?"WRPROT ":"", (map->flags&MAP_ATTRIB)?"ATTRIB ":"", (map->flags&MAP_USE_WAIT)?"USE_WAIT ":""); if (map->map >= MAX_WIN){ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__, map->map); return -1; } if (map->flags & MAP_ACTIVE) { unsigned int clock, speed = map->speed; unsigned long mecr; /* * When clients issue RequestMap, the access speed is not always * properly configured. Choose some sensible defaults. */ if (speed == 0) { if (skt->cs_state.Vcc == 33) speed = SA1100_PCMCIA_3V_MEM_ACCESS; else speed = SA1100_PCMCIA_5V_MEM_ACCESS; } clock = cpufreq_get(0); /* Fixme: MECR is not pre-empt safe. */ mecr = MECR; if (map->flags & MAP_ATTRIB) { MECR_BSA_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock)); skt->speed_attr = speed; } else { MECR_BSM_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock)); skt->speed_mem = speed; } DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n", __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock, MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), sock, MECR_BSIO_GET(mecr, sock)); MECR = mecr; } start = (map->flags & MAP_ATTRIB) ? skt->phys_attr : skt->phys_mem; if (map->sys_stop == 0) map->sys_stop = PAGE_SIZE-1; map->sys_stop -= map->sys_start; map->sys_stop += start; map->sys_start = start; skt->mem_map[map->map] = *map; return 0; } /* sa1100_pcmcia_set_mem_map() */
/* sa1100_pcmcia_set_mem_map() * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the set_mem_map() operation for the in-kernel PCMCIA * service (formerly SS_SetMemMap in Card Services). We configure * the map speed as requested, but override the address ranges * supplied by Card Services. * * Returns: 0 on success, -1 on error */ static int sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map){ unsigned int clock, speed; unsigned long mecr, start; DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock); DEBUG(4, "\tmap %u speed %u\n\tsys_start %#lx\n" "\tsys_stop %#lx\n\tcard_start %#x\n" "\tflags: %s%s%s%s%s%s%s%s\n", map->map, map->speed, map->sys_start, map->sys_stop, map->card_start, (map->flags==0)?"<NONE>":"", (map->flags&MAP_ACTIVE)?"ACTIVE ":"", (map->flags&MAP_16BIT)?"16BIT ":"", (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"", (map->flags&MAP_0WS)?"0WS ":"", (map->flags&MAP_WRPROT)?"WRPROT ":"", (map->flags&MAP_ATTRIB)?"ATTRIB ":"", (map->flags&MAP_USE_WAIT)?"USE_WAIT ":""); if(map->map>=MAX_WIN){ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__, map->map); return -1; } if(map->flags&MAP_ACTIVE){ /* When clients issue RequestMap, the access speed is not always * properly configured: */ if(map->speed > 0) speed = map->speed; else switch(sa1100_pcmcia_socket[sock].cs_state.Vcc){ case 33: speed = SA1100_PCMCIA_3V_MEM_ACCESS; break; default: speed = SA1100_PCMCIA_5V_MEM_ACCESS; } clock = cpufreq_get(0); mecr=MECR; if(map->flags&MAP_ATTRIB){ MECR_BSA_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock)); sa1100_pcmcia_socket[sock].speed_attr=speed; } else { MECR_BSM_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock)); sa1100_pcmcia_socket[sock].speed_mem=speed; } DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n", __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock, MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), sock, MECR_BSIO_GET(mecr, sock)); MECR=mecr; } start=map->sys_start; if(map->sys_stop==0) map->sys_stop=PAGE_SIZE-1; map->sys_start=(map->flags & MAP_ATTRIB)?\ sa1100_pcmcia_socket[sock].phys_attr:\ sa1100_pcmcia_socket[sock].phys_mem; map->sys_stop=map->sys_start+(map->sys_stop-start); sa1100_pcmcia_socket[sock].mem_map[map->map]=*map; return 0; } /* sa1100_pcmcia_set_mem_map() */