📄 pxa.c
字号:
* * 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() *//* pxa_pcmcia_get_mem_map() * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the get_mem_map() operation for the in-kernel PCMCIA * service (formerly SS_GetMemMap in Card Services). Just returns a * memory map descriptor which was assigned earlier by a * set_mem_map() request. * * Returns: 0 on success, -1 if the map index was out of range */static int pxa_pcmcia_get_mem_map(unsigned int sock, struct pccard_mem_map *map){ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock); if(map->map>=MAX_WIN){ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__, map->map); return -1; } *map=pxa_pcmcia_socket[sock].mem_map[map->map]; return 0;}/* 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() */#if defined(CONFIG_PROC_FS)/* pxa_pcmcia_proc_setup() * ^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the proc_setup() operation for the in-kernel PCMCIA * service (formerly SS_ProcSetup in Card Services). * * Returns: 0 on success, -1 on error */static void pxa_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base){ struct proc_dir_entry *entry; DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock); if((entry=create_proc_entry("status", 0, base))==NULL){ printk(KERN_ERR "Unable to install \"status\" procfs entry\n"); return; } entry->read_proc=pxa_pcmcia_proc_status; entry->data=(void *)sock;}/* pxa_pcmcia_proc_status() * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the /proc/bus/pccard/??/status file. * * Returns: the number of characters added to the buffer */static int pxa_pcmcia_proc_status(char *buf, char **start, off_t pos, int count, int *eof, void *data){ char *p=buf; unsigned int sock=(unsigned int)data; unsigned int clock = get_lclk_frequency_10khz(); unsigned long mecr = MECR; p+=sprintf(p, "k_flags : %s%s%s%s%s%s%s\n", pxa_pcmcia_socket[sock].k_state.detect?"detect ":"", pxa_pcmcia_socket[sock].k_state.ready?"ready ":"", pxa_pcmcia_socket[sock].k_state.bvd1?"bvd1 ":"", pxa_pcmcia_socket[sock].k_state.bvd2?"bvd2 ":"", pxa_pcmcia_socket[sock].k_state.wrprot?"wrprot ":"", pxa_pcmcia_socket[sock].k_state.vs_3v?"vs_3v ":"", pxa_pcmcia_socket[sock].k_state.vs_Xv?"vs_Xv ":""); p+=sprintf(p, "status : %s%s%s%s%s%s%s%s%s\n", pxa_pcmcia_socket[sock].k_state.detect?"SS_DETECT ":"", pxa_pcmcia_socket[sock].k_state.ready?"SS_READY ":"", pxa_pcmcia_socket[sock].cs_state.Vcc?"SS_POWERON ":"", pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\ "SS_IOCARD ":"", (pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD && pxa_pcmcia_socket[sock].k_state.bvd1)?"SS_STSCHG ":"", ((pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 && (pxa_pcmcia_socket[sock].k_state.bvd1==0))?"SS_BATDEAD ":"", ((pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 && (pxa_pcmcia_socket[sock].k_state.bvd2==0))?"SS_BATWARN ":"", pxa_pcmcia_socket[sock].k_state.vs_3v?"SS_3VCARD ":"", pxa_pcmcia_socket[sock].k_state.vs_Xv?"SS_XVCARD ":""); p+=sprintf(p, "mask : %s%s%s%s%s\n", pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_DETECT?\ "SS_DETECT ":"", pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_READY?\ "SS_READY ":"", pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_BATDEAD?\ "SS_BATDEAD ":"", pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_BATWARN?\ "SS_BATWARN ":"", pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_STSCHG?\ "SS_STSCHG ":""); p+=sprintf(p, "cs_flags : %s%s%s%s%s\n", pxa_pcmcia_socket[sock].cs_state.flags&SS_PWR_AUTO?\ "SS_PWR_AUTO ":"", pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\ "SS_IOCARD ":"", pxa_pcmcia_socket[sock].cs_state.flags&SS_RESET?\ "SS_RESET ":"", pxa_pcmcia_socket[sock].cs_state.flags&SS_SPKR_ENA?\ "SS_SPKR_ENA ":"", pxa_pcmcia_socket[sock].cs_state.flags&SS_OUTPUT_ENA?\ "SS_OUTPUT_ENA ":""); p+=sprintf(p, "Vcc : %d\n", pxa_pcmcia_socket[sock].cs_state.Vcc); p+=sprintf(p, "Vpp : %d\n", pxa_pcmcia_socket[sock].cs_state.Vpp); p+=sprintf(p, "irq : %d\n", pxa_pcmcia_socket[sock].cs_state.io_irq); p+=sprintf(p, "I/O : %u (%u)\n", pxa_pcmcia_socket[sock].speed_io, sock ? pxa_pcmcia_cmd_time(clock, ((MCIO1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) : pxa_pcmcia_cmd_time(clock, ((MCIO0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK))); p+=sprintf(p, "attribute: %u (%u)\n", pxa_pcmcia_socket[sock].speed_attr, sock ? pxa_pcmcia_cmd_time(clock, ((MCATT1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) : pxa_pcmcia_cmd_time(clock, ((MCATT0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK))); p+=sprintf(p, "common : %u (%u)\n", pxa_pcmcia_socket[sock].speed_mem, sock ? pxa_pcmcia_cmd_time(clock, ((MCMEM1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) : pxa_pcmcia_cmd_time(clock, ((MCMEM0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK))); return p-buf;}#endif /* defined(CONFIG_PROC_FS) */#ifdef CONFIG_CPU_FREQ/* pxa_pcmcia_update_mecr() * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * When pxa_pcmcia_notifier() decides that a MECR adjustment (due * to a core clock frequency change) is needed, this routine establishes * new BS_xx values consistent with the clock speed `clock'. */static void pxa_pcmcia_update_mecr(unsigned int clock){ unsigned int sock; for(sock = 0; sock < PXA_PCMCIA_MAX_SOCK; ++sock){ // REVISIT: MCXX macros needed here // MECR_BSIO_SET(mecr, sock,// pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_io,// clock)); // MECR_BSA_SET(mecr, sock,// pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_attr,// clock)); // MECR_BSM_SET(mecr, sock,// pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_mem,// clock)); }}/* pxa_pcmcia_notifier() * ^^^^^^^^^^^^^^^^^^^^^^^^ * When changing the processor core clock frequency, it is necessary * to adjust the MECR timings accordingly. We've recorded the timings * requested by Card Services, so this is just a matter of finding * out what our current speed is, and then recomputing the new MECR * values. * * Returns: 0 on success, -1 on error */static int pxa_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data){ struct cpufreq_info *ci = data; switch(val){ case CPUFREQ_MINMAX: break; case CPUFREQ_PRECHANGE: if(ci->new_freq > ci->old_freq){ DEBUG(2, "%s(): new frequency %u.%uMHz > %u.%uMHz, pre-updating\n", __FUNCTION__, ci->new_freq / 1000, (ci->new_freq / 100) % 10, ci->old_freq / 1000, (ci->old_freq / 100) % 10); pxa_pcmcia_update_mecr(ci->new_freq); } break; case CPUFREQ_POSTCHANGE: if(ci->new_freq < ci->old_freq){ DEBUG(2, "%s(): new frequency %u.%uMHz < %u.%uMHz, post-updating\n", __FUNCTION__, ci->new_freq / 1000, (ci->new_freq / 100) % 10, ci->old_freq / 1000, (ci->old_freq / 100) % 10); pxa_pcmcia_update_mecr(ci->new_freq); } break; default: printk(KERN_ERR "%s(): unknown CPU frequency event %lx\n", __FUNCTION__, val); return -1; } return 0;}static struct notifier_block pxa_pcmcia_notifier_block = { notifier_call: pxa_pcmcia_notifier};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -