📄 mmc_core.c
字号:
void mmc_unregister_slot_driver( struct mmc_slot_driver *sdrive ){ int i; DEBUG(2,"\n"); for ( i = 0 ; i < g_mmc_dev.num_slots ; i++ ) mmc_eject(i); if ( sdrive == g_mmc_dev.sdrive ) { g_mmc_dev.sdrive->cleanup(); g_mmc_dev.sdrive = NULL; }}EXPORT_SYMBOL(mmc_register_slot_driver);EXPORT_SYMBOL(mmc_unregister_slot_driver);/******************************************************************/static struct pm_dev *mmc_pm_dev;static int mmc_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data){ int i; DEBUG(0,": pm callback %d\n", req ); switch (req) { case PM_SUSPEND: /* Enter D1-D3 */ g_mmc_dev.suspended = 1; break; case PM_RESUME: /* Enter D0 */ if ( g_mmc_dev.suspended ) { g_mmc_dev.suspended = 0; g_mmc_dev.state = 0; // Clear the old state for ( i = 0 ; i < g_mmc_dev.num_slots ; i++ ) { mmc_eject(i); if ( !g_mmc_dev.sdrive->is_empty(i) ) mmc_insert(i); } } break; } return 0;}#ifdef CONFIG_CEE#include <linux/device.h>static int mmc_suspend(struct device *dev, u32 state, u32 level);static int mmc_resume(struct device *dev, u32 level);static struct device_driver mmc_driver_ldm = { name: "mmc", devclass: NULL, probe: NULL, suspend: mmc_suspend, resume: mmc_resume, scale: NULL, remove: NULL,};static struct device mmc_device_ldm = { name: "MMC", bus_id: "mmc", driver: NULL, power_state: DPM_POWER_ON,};static voidmmc_ldm_register(void){#ifdef CONFIG_ARCH_MAINSTONE extern void pxaopb_driver_register(struct device_driver *driver); extern void pxaopb_device_register(struct device *device); pxaopb_driver_register(&mmc_driver_ldm); pxaopb_device_register(&mmc_device_ldm);#endif#ifdef CONFIG_ARCH_OMAP extern void mpu_public_driver_register(struct device_driver *driver); extern void mpu_public_device_register(struct device *device); mpu_public_driver_register(&mmc_driver_ldm); mpu_public_device_register(&mmc_device_ldm);#endif#ifdef CONFIG_ARCH_MX2ADS extern void mx21_ldm_device_register(struct device *device); extern void mx21_ldm_driver_register(struct device_driver *driver); mx21_ldm_driver_register(&mmc_driver_ldm); mx21_ldm_device_register(&mmc_device_ldm);#endif}static voidmmc_ldm_unregister(void){#ifdef CONFIG_ARCH_MAINSTONE extern void pxaopb_driver_unregister(struct device_driver *driver); extern void pxaopb_device_unregister(struct device *device); pxaopb_device_unregister(&mmc_device_ldm); pxaopb_driver_unregister(&mmc_driver_ldm);#endif#ifdef CONFIG_ARCH_OMAP extern void mpu_public_driver_unregister(struct device_driver *driver); extern void mpu_public_device_unregister(struct device *device); mpu_public_driver_unregister(&mmc_driver_ldm); mpu_public_device_unregister(&mmc_device_ldm);#endif#ifdef CONFIG_ARCH_MX2ADS extern void mx21_ldm_device_unregister(struct device *device); extern void mx21_ldm_driver_unregister(struct device_driver *driver); mx21_ldm_device_unregister(&mmc_device_ldm); mx21_ldm_driver_unregister(&mmc_driver_ldm);#endif}static intmmc_resume(struct device *dev, u32 level){ int i; switch (level) { case RESUME_RESTORE_STATE: case RESUME_ENABLE: case RESUME_POWER_ON: /* Enter D0 */ if ( g_mmc_dev.suspended ) { g_mmc_dev.suspended = 0; g_mmc_dev.state = 0; // Clear the old state for ( i = 0 ; i < g_mmc_dev.num_slots ; i++ ) { mmc_eject(i); if ( !g_mmc_dev.sdrive->is_empty(i) ) mmc_insert(i); } } break; } return 0;}static intmmc_suspend(struct device *dev, u32 state, u32 level){ switch (level) { case SUSPEND_NOTIFY: case SUSPEND_SAVE_STATE: case SUSPEND_DISABLE: case SUSPEND_POWER_DOWN: /* Enter D1-D3 */ g_mmc_dev.suspended = 1; break; } return 0;}#endif /* CONFIG_CEE *//****************************************************************** * TODO: These would be better handled by driverfs * For the moment, we'll just eject and insert everything ******************************************************************/int mmc_do_eject(ctl_table *ctl, int write, struct file * filp, void *buffer, size_t *lenp){ mmc_eject(0); return 0;}int mmc_do_insert(ctl_table *ctl, int write, struct file * filp, void *buffer, size_t *lenp){ mmc_insert(0); return 0;}static struct ctl_table mmc_sysctl_table[] ={ { 1, "debug", &g_mmc_debug, sizeof(int), 0666, NULL, &proc_dointvec }, { 2, "eject", NULL, 0, 0600, NULL, &mmc_do_eject }, { 3, "insert", NULL, 0, 0600, NULL, &mmc_do_insert }, {0}};static struct ctl_table mmc_dir_table[] ={ {BUS_MMC, "mmc", NULL, 0, 0555, mmc_sysctl_table}, {0}};static struct ctl_table bus_dir_table[] = { {CTL_BUS, "bus", NULL, 0, 0555, mmc_dir_table}, {0}};static struct ctl_table_header *mmc_sysctl_header;/* Wangzheng */static int mmc_proc_read_device(char *page, char **start, off_t off, int count, int *eof, void *data){ struct mmc_dev *dev = (struct mmc_dev *)data; char *p = page; int len = 0; int i; if (!dev || !dev->sdrive) return 0; for ( i = 0 ; i < dev->num_slots ; i++ ) { struct mmc_slot *slot = &dev->slot[i]; p += sprintf(p, "Slot #%d\n", i); p += sprintf(p, " State %s (%d)\n", card_state_to_string(slot->state), slot->state); if ( slot->state != CARD_STATE_EMPTY ) { if(!slot->sd) { p += sprintf(p, " Media %s\n", (slot->media_driver ? slot->media_driver->name : "unknown")); p += sprintf(p, " CID mid=%d\n", slot->cid.cid_mmc.mid); p += sprintf(p, " oid=%d\n", slot->cid.cid_mmc.oid); p += sprintf(p, " pnm=%s\n", slot->cid.cid_mmc.pnm); p += sprintf(p, " prv=%d.%d\n", slot->cid.cid_mmc.prv>>4, slot->cid.cid_mmc.prv&0xf); p += sprintf(p, " psn=0x%08x\n", slot->cid.cid_mmc.psn); p += sprintf(p, " mdt=%d/%d\n", slot->cid.cid_mmc.mdt&0xf, (slot->cid.cid_mmc.mdt>>4)+2000); p += sprintf(p, " CSD csd_structure=%d\n", slot->csd.csd_mmc.csd_structure); p += sprintf(p, " spec_vers=%d\n", slot->csd.csd_mmc.spec_vers); p += sprintf(p, " taac=0x%02x\n", slot->csd.csd_mmc.taac); p += sprintf(p, " nsac=0x%02x\n", slot->csd.csd_mmc.nsac); p += sprintf(p, " tran_speed=0x%02x\n", slot->csd.csd_mmc.tran_speed); p += sprintf(p, " ccc=0x%04x\n", slot->csd.csd_mmc.ccc); p += sprintf(p, " read_bl_len=%d\n", slot->csd.csd_mmc.read_bl_len); p += sprintf(p, " read_bl_partial=%d\n", slot->csd.csd_mmc.read_bl_partial); p += sprintf(p, " write_blk_misalign=%d\n", slot->csd.csd_mmc.write_blk_misalign); p += sprintf(p, " read_blk_misalign=%d\n", slot->csd.csd_mmc.read_blk_misalign); p += sprintf(p, " dsr_imp=%d\n", slot->csd.csd_mmc.dsr_imp); p += sprintf(p, " c_size=%d\n", slot->csd.csd_mmc.c_size); p += sprintf(p, " vdd_r_curr_min=%d\n", slot->csd.csd_mmc.vdd_r_curr_min); p += sprintf(p, " vdd_r_curr_max=%d\n", slot->csd.csd_mmc.vdd_r_curr_max); p += sprintf(p, " vdd_w_curr_min=%d\n", slot->csd.csd_mmc.vdd_w_curr_min); p += sprintf(p, " vdd_w_curr_max=%d\n", slot->csd.csd_mmc.vdd_w_curr_max); p += sprintf(p, " c_size_mult=%d\n", slot->csd.csd_mmc.c_size_mult); p += sprintf(p, " wp_grp_size=%d\n", slot->csd.csd_mmc.wp_grp_size); p += sprintf(p, " wp_grp_enable=%d\n", slot->csd.csd_mmc.wp_grp_enable); p += sprintf(p, " default_ecc=%d\n", slot->csd.csd_mmc.default_ecc); p += sprintf(p, " r2w_factor=%d\n", slot->csd.csd_mmc.r2w_factor); p += sprintf(p, " write_bl_len=%d\n", slot->csd.csd_mmc.write_bl_len); p += sprintf(p, " write_bl_partial=%d\n", slot->csd.csd_mmc.write_bl_partial); p += sprintf(p, " file_format_grp=%d\n", slot->csd.csd_mmc.file_format_grp); p += sprintf(p, " copy=%d\n", slot->csd.csd_mmc.copy); p += sprintf(p, " perm_write_protect=%d\n", slot->csd.csd_mmc.perm_write_protect); p += sprintf(p, " tmp_write_protect=%d\n", slot->csd.csd_mmc.tmp_write_protect); p += sprintf(p, " file_format=%d\n", slot->csd.csd_mmc.file_format); p += sprintf(p, " ecc=%d\n", slot->csd.csd_mmc.ecc); switch (slot->csd.csd_mmc.csd_structure) { case CSD_STRUCT_VER_1_0: case CSD_STRUCT_VER_1_1: p += sprintf(p, " sector_size=%d\n", slot->csd.csd_mmc.erase.v22.sector_size); p += sprintf(p, " erase_grp_size=%d\n", slot->csd.csd_mmc.erase.v22.erase_grp_size); break; case CSD_STRUCT_VER_1_2: default: p += sprintf(p, " erase_grp_size=%d\n", slot->csd.csd_mmc.erase.v31.erase_grp_size); p += sprintf(p, " erase_grp_mult=%d\n", slot->csd.csd_mmc.erase.v31.erase_grp_mult); break; } } else { p += sprintf(p, " Media %s\n", (slot->media_driver ? slot->media_driver->name : "unknown")); p += sprintf(p, " CID mid=%d\n", slot->cid.cid_sd.mid); p += sprintf(p, " oid=%d\n", slot->cid.cid_sd.oid); p += sprintf(p, " pnm=%s\n", slot->cid.cid_sd.pnm); p += sprintf(p, " prv=%d.%d\n", slot->cid.cid_sd.prv>>4, slot->cid.cid_sd.prv&0xf); p += sprintf(p, " psn=0x%08x\n", slot->cid.cid_sd.psn); p += sprintf(p, " mdt=%d/%d\n", slot->cid.cid_sd.mdt>>4, (slot->cid.cid_sd.mdt&0xf)+2000); p += sprintf(p, " CSD csd_structure=%d\n", slot->csd.csd_sd.csd_structure); p += sprintf(p, " spec_vers=%d\n", slot->csd.csd_sd.spec_vers); p += sprintf(p, " taac=0x%02x\n", slot->csd.csd_sd.taac); p += sprintf(p, " nsac=0x%02x\n", slot->csd.csd_sd.nsac); p += sprintf(p, " tran_speed=0x%02x\n", slot->csd.csd_sd.tran_speed); p += sprintf(p, " ccc=0x%04x\n", slot->csd.csd_sd.ccc); p += sprintf(p, " read_bl_len=%d\n", slot->csd.csd_sd.read_bl_len); p += sprintf(p, " read_bl_partial=%d\n", slot->csd.csd_sd.read_bl_partial); p += sprintf(p, " write_blk_misalign=%d\n", slot->csd.csd_sd.write_blk_misalign); p += sprintf(p, " read_blk_misalign=%d\n", slot->csd.csd_sd.read_blk_misalign); p += sprintf(p, " dsr_imp=%d\n", slot->csd.csd_sd.dsr_imp); p += sprintf(p, " c_size=%d\n", slot->csd.csd_sd.c_size); p += sprintf(p, " vdd_r_curr_min=%d\n", slot->csd.csd_sd.vdd_r_curr_min); p += sprintf(p, " vdd_r_curr_max=%d\n", slot->csd.csd_sd.vdd_r_curr_max); p += sprintf(p, " vdd_w_curr_min=%d\n", slot->csd.csd_sd.vdd_w_curr_min); p += sprintf(p, " vdd_w_curr_max=%d\n", slot->csd.csd_sd.vdd_w_curr_max); p += sprintf(p, " c_size_mult=%d\n", slot->csd.csd_sd.c_size_mult); p += sprintf(p, " erase_blk_enable=%d\n", slot->csd.csd_sd.erase_blk_enable); p += sprintf(p, " erase_sector_size=%d\n", slot->csd.csd_sd.erase_sector_size); p += sprintf(p, " wp_grp_size=%d\n", slot->csd.csd_sd.wp_grp_size); p += sprintf(p, " wp_grp_enable=%d\n", slot->csd.csd_sd.wp_grp_enable); p += sprintf(p, " r2w_factor=%d\n", slot->csd.csd_sd.r2w_factor); p += sprintf(p, " write_bl_len=%d\n", slot->csd.csd_sd.write_bl_len); p += sprintf(p, " write_bl_partial=%d\n", slot->csd.csd_sd.write_bl_partial); p += sprintf(p, " file_format_grp=%d\n", slot->csd.csd_sd.file_format_grp); p += sprintf(p, " copy=%d\n", slot->csd.csd_sd.copy); p += sprintf(p, " perm_write_protect=%d\n", slot->csd.csd_sd.perm_write_protect); p += sprintf(p, " tmp_write_protect=%d\n", slot->csd.csd_sd.tmp_write_protect); p += sprintf(p, " file_format=%d\n", slot->csd.csd_sd.file_format); } } } len = (p - page) - off; *start = page + off; return len;}/******************************************************************/void mmc_protocol_single_card( struct mmc_dev *dev, int state_flags );extern struct mmc_media_module media_module;static int __init mmc_init(void) { DEBUG(1, "Init MMC subsystem\n"); mmc_sysctl_header = register_sysctl_table(bus_dir_table, 0 ); tasklet_init(&g_mmc_dev.task,mmc_tasklet_action,(unsigned long)&g_mmc_dev); g_mmc_dev.protocol = mmc_protocol_single_card; proc_mmc_dir = proc_mkdir("mmc", proc_bus); if ( proc_mmc_dir ) create_proc_read_entry("device", 0, proc_mmc_dir, mmc_proc_read_device, &g_mmc_dev); mmc_pm_dev = pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, mmc_pm_callback); #ifdef CONFIG_CEE mmc_ldm_register();#endif /* CONFIG_CEE */ media_module.init(); return 0;}static void __exit mmc_exit(void){ DEBUG(1,"\n"); media_module.cleanup(); unregister_sysctl_table(mmc_sysctl_header); tasklet_kill(&g_mmc_dev.task); if ( proc_mmc_dir ) { remove_proc_entry("device", proc_mmc_dir); remove_proc_entry("mmc", proc_bus); } pm_unregister(mmc_pm_dev); #ifdef CONFIG_CEE mmc_ldm_unregister();#endif /* CONFIG_CEE */ }module_init(mmc_init);module_exit(mmc_exit);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -