/* * pm_pc6_exit: * * Execute pc6 exit for a node. * mic_ctx: The driver context of the node. */ int pm_pc6_exit(mic_ctx_t *mic_ctx) { int err = 0; sbox_host_pm_state_t hpmstate_regval; sbox_pcu_ctrl_t ctrl_regval; uint8_t tdp_vid = 0; uint8_t is_pll_locked; uint32_t wait_cnt; int i; if (!check_host_state(mic_ctx, PM_IDLE_STATE_PC6)) { PM_DEBUG("Wrong Host PM state. State = %d\n", get_host_state(mic_ctx)); err = -EINVAL; goto restore_registers; } hpmstate_regval.value = pm_reg_read(mic_ctx, SBOX_HOST_PMSTATE); tdp_vid = hpmstate_regval.bits.tdp_vid; PM_DEBUG("TDP_VID value obtained from Host PM Register = %d",tdp_vid); PM_DEBUG("Setting voltage to %dV using SVID Control\n",tdp_vid); err = set_vid_knc(mic_ctx, tdp_vid); if (err != 0) { printk(KERN_ERR "%s Failed PC6 entry...error in setting VID\n", __func__); goto restore_registers; } ctrl_regval.value = pm_reg_read(mic_ctx, SBOX_PCU_CONTROL); program_mclk_shutdown(mic_ctx, false); program_prevent_C3Exit(mic_ctx, false); for(wait_cnt = 0; wait_cnt < 200; wait_cnt++) { ctrl_regval.value = pm_reg_read(mic_ctx,SBOX_PCU_CONTROL); is_pll_locked = ctrl_regval.bits.mclk_pll_lock; if(likely(is_pll_locked)) break; msleep(10); } if(wait_cnt >= 200) { PM_DEBUG("mclk_pll_locked bit is not set.\n"); err = -EAGAIN; goto restore_registers; } ctrl_regval.bits.grpB_pwrgood_mask = 0; pm_reg_write(ctrl_regval.value, mic_ctx, SBOX_PCU_CONTROL); if (!hw_active(mic_ctx)) { PM_DEBUG("Timing out waiting for hw to become active"); goto restore_registers; } for(wait_cnt = 0; wait_cnt < 200; wait_cnt++) { if ((get_card_state(mic_ctx)) == PM_IDLE_STATE_PC0) break; msleep(10); } if(wait_cnt >= 200) { PM_DEBUG("PC6 Exit not complete.\n"); err = -EFAULT; goto restore_registers; } mic_ctx->micpm_ctx.idle_state = PM_IDLE_STATE_PC0; for (i = 0; i <= mic_data.dd_numdevs; i++) { if (micscif_get_nodedep(mic_get_scifnode_id(mic_ctx), i) == DEP_STATE_DISCONNECTED) { micscif_set_nodedep(mic_get_scifnode_id(mic_ctx), i, DEP_STATE_DEPENDENT); } } PM_PRINT("Node %d exited PC6\n", mic_get_scifnode_id(mic_ctx)); goto exit; restore_registers: restore_pc6_registers(mic_ctx, false); exit: atomic_set(&mic_ctx->gate_interrupt, 0); tasklet_schedule(&mic_ctx->bi_dpc); return err; }
int check_card_state(mic_ctx_t *mic_ctx, PM_IDLE_STATE state) { PM_IDLE_STATE card_state = get_card_state(mic_ctx); return (state == card_state) ? 1 : 0; }
int pm_pc3_to_pc6_entry(mic_ctx_t *mic_ctx) { int err; sbox_pcu_ctrl_t ctrl_regval; gbox_pm_control pmctrl_reg; sbox_core_freq_t core_freq_reg; if ((get_card_state(mic_ctx)) != PM_IDLE_STATE_PC3) { PM_DEBUG("Card not ready to go to PC6. \n"); err = -EAGAIN; goto exit; } if (atomic_cmpxchg(&mic_ctx->gate_interrupt, 0, 1) == 1) { PM_DEBUG("Cannot gate interrupt handler while it is in use\n"); err = -EFAULT; goto exit; } program_prevent_C3Exit(mic_ctx, true); program_mclk_shutdown(mic_ctx, true); /* Wait for uos to become idle. */ if (!hw_idle(mic_ctx)) { program_mclk_shutdown(mic_ctx, false); if (!hw_idle(mic_ctx)) { program_prevent_C3Exit(mic_ctx, false); PM_DEBUG("Card not ready to go to PC6. \n"); err = -EAGAIN; goto intr_ungate; } else { program_mclk_shutdown(mic_ctx, true); } } pmctrl_reg.value = pm_reg_read(mic_ctx, GBOX_PM_CTRL); pmctrl_reg.bits.in_pckgc6 = 1; pm_reg_write(pmctrl_reg.value, mic_ctx, GBOX_PM_CTRL); core_freq_reg.value = pm_reg_read(mic_ctx, SBOX_COREFREQ); core_freq_reg.bits.booted = 0; pm_reg_write(core_freq_reg.value, mic_ctx, SBOX_COREFREQ); udelay(500); ctrl_regval.value = pm_reg_read(mic_ctx, SBOX_PCU_CONTROL); ctrl_regval.bits.grpB_pwrgood_mask = 1; pm_reg_write(ctrl_regval.value, mic_ctx, SBOX_PCU_CONTROL); err = set_vid_knc(mic_ctx, 0); if (err != 0) { PM_DEBUG("Aborting PC6 entry...Failed to set VID\n"); restore_pc6_registers(mic_ctx, true); goto intr_ungate; } mic_ctx->micpm_ctx.idle_state = PM_IDLE_STATE_PC6; set_host_state(mic_ctx, PM_IDLE_STATE_PC6); dma_prep_suspend(mic_ctx->dma_handle); PM_PRINT("Node %d entered PC6\n", mic_get_scifnode_id(mic_ctx)); return err; intr_ungate: atomic_set(&mic_ctx->gate_interrupt, 0); tasklet_schedule(&mic_ctx->bi_dpc); exit: return err; }
int sctest(void) { SCARDCONTEXT ctx; SCARDHANDLE card; int rc; char *readers = NULL; char *reader_dev_name = NULL; struct card_state card_state; enum conventions { DIRECT, INVERSE } convention = DIRECT; struct c_apdu c_apdu; struct r_apdu r_apdu; printf("creating context... "); if (SCardEstablishContext(opts.scope, NULL, NULL, &ctx) != SCARD_S_SUCCESS) return fail(1, "failed\n"); else printf("ok\n"); if ((rc = get_card_readers(ctx, &readers)) != SCARD_S_SUCCESS) { if (rc == SCARD_E_NO_READERS_AVAILABLE) return fail(-1, "no card readers present in the system\n"); else return fail(-1, "SCardListReaders error %d", rc); } switch (opts.mode) { case LIST_READERS: print_readers(readers); break; case NORMAL: default: if ((reader_dev_name = get_multistring(readers, opts.reader)) == NULL) { SCardReleaseContext(ctx); return fail(-1, "no such card reader\n"); } else printf("using card reader \"%s\"\n", reader_dev_name); printf("connecting to card reader... "); if ((rc = SCardConnect(ctx, reader_dev_name, SCARD_SHARE_DIRECT, 0, &card, SCARD_PROTOCOL_UNDEFINED)) != SCARD_S_SUCCESS) { SCardReleaseContext(ctx); switch (rc) { case SCARD_E_NO_SMARTCARD: return fail(-1, "no smart card in device\n"); break; default: return fail(-1, "SCardConnect: error %d", rc); break; } } else printf("ok\n"); if ((rc = get_card_state(card, &card_state)) != SCARD_S_SUCCESS) { SCardDisconnect(card, DEFAULT_DISCONNECT_ACTION); SCardReleaseContext(ctx); switch (rc) { default: return fail(-1, "SCardStatus: error %d\n"); } } print_card_state(&card_state); printf("checking atr for conformance to emv... "); if (is_emv_atr(1, &card_state)) printf("ok\n"); # define FILE_STR "1PAY.SYS.DDF01" /* TODO */ if (card_state.proto == SCARD_PROTOCOL_T0) { c_apdu.cla = 0x0; c_apdu.ins = 0xb2; c_apdu.p1 = 0x4; c_apdu.p2 = 0x0; c_apdu.body.len = strlen(FILE_STR); strcpy(c_apdu.body.data, FILE_STR); c_apdu.body.max_r_len = 0; if (ttl_io(card, card_state.proto, &c_apdu, &r_apdu) == -1) printf("ttl_io failed\n"); else { printf("ttl_io finished ok\n"); print_r_apdu(NULL, &r_apdu); } } else if (card_state.proto == SCARD_PROTOCOL_T1) { } SCardDisconnect(card, DEFAULT_DISCONNECT_ACTION); break; } SCardReleaseContext(ctx); return 0; }