void usb_spi_board_disable(struct usb_spi_config const *config) { CPRINTS("usb_spi disable"); spi_enable(CONFIG_SPI_FLASH_PORT, 0); disable_ec_ap_spi(); /* Disconnect SPI peripheral to tri-state pads */ /* Disable internal pull up */ GWRITE_FIELD(PINMUX, DIOA14_CTL, PU, 0); /* TODO: Implement way to get the gpio */ ASSERT(GREAD(PINMUX, GPIO0_GPIO7_SEL) == GC_PINMUX_DIOA4_SEL); ASSERT(GREAD(PINMUX, GPIO0_GPIO8_SEL) == GC_PINMUX_DIOA8_SEL); ASSERT(GREAD(PINMUX, GPIO0_GPIO9_SEL) == GC_PINMUX_DIOA14_SEL); /* Set SPI MOSI, CLK, and CS_L as inputs */ GWRITE(PINMUX, DIOA4_SEL, GC_PINMUX_GPIO0_GPIO7_SEL); GWRITE(PINMUX, DIOA8_SEL, GC_PINMUX_GPIO0_GPIO8_SEL); GWRITE(PINMUX, DIOA14_SEL, GC_PINMUX_GPIO0_GPIO9_SEL); /* * TODO(crosbug.com/p/52366): remove once sys_rst just resets the TPM * instead of cr50. * Resetting the EC and AP cause sys_rst to be asserted currently that * will cause cr50 to do a soft reset. Delay the end of the transaction * to prevent cr50 from resetting during a series of usb_spi calls. */ hook_call_deferred(&update_finished_data, 1 * SECOND); }
Word ESPORD() { Word i,n,m,C,H,H1,H11; Step1: /* Read in the number of variables. */ do C = CREAD(); while (!DIGIT(C)); BKSP(); n = GREAD() - 1; FILINE(); FILINE(); Step2: /* Read in the rows. */ H = NIL; for (;;) { C = CREAD(); BKSP(); if (C == '.') break; H1 = NIL; for (i=1; i<=n; i++) { m = GREAD(); switch(m) { case 1: H11 = GTOP; break; case 10: H11 = EQOP; break; case 11: H11 = GEOP; break; case 100: H11 = LTOP; break; case 101: H11 = NEOP; break; case 110: H11 = LEOP; break; case 111: H11 = TAOP; break; default: FAIL("ESPORD","Illegal output from espresso."); } H1 = COMP(H11,H1); } FILINE(); H1 = INV(H1); H = COMP(H1,H); } H = INV(H); FILINE(); Return: /* Prepare for return. */ return(H); }
static int do_flash_op(enum flash_op op, int is_info_bank, int byte_offset, int words) { volatile uint32_t *fsh_pe_control; uint32_t opcode, tmp, errors; int retry_count, max_attempts, extra_prog_pulse, i; int timedelay_us = 100; uint32_t prev_error = 0; /* Make sure the smart program/erase algorithms are enabled. */ if (!GREAD(FLASH, FSH_TIMING_PROG_SMART_ALGO_ON) || !GREAD(FLASH, FSH_TIMING_ERASE_SMART_ALGO_ON)) { CPRINTF("%s:%d\n", __func__, __LINE__); return EC_ERROR_UNIMPLEMENTED; } /* Error status is self-clearing. Read it until it does (we hope). */ for (i = 0; i < 50; i++) { tmp = GREAD(FLASH, FSH_ERROR); if (!tmp) break; usleep(timedelay_us); } /* If we can't clear the error status register then something is wrong. */ if (tmp) { CPRINTF("%s:%d\n", __func__, __LINE__); return EC_ERROR_UNKNOWN; } /* We have two flash banks. Adjust offset and registers accordingly. */ if (is_info_bank) { /* Only INFO bank operations are supported. */ fsh_pe_control = GREG32_ADDR(FLASH, FSH_PE_CONTROL1); } else if (byte_offset >= CFG_FLASH_HALF) { byte_offset -= CFG_FLASH_HALF; fsh_pe_control = GREG32_ADDR(FLASH, FSH_PE_CONTROL1); } else { fsh_pe_control = GREG32_ADDR(FLASH, FSH_PE_CONTROL0); } /* What are we doing? */ switch (op) { case OP_ERASE_BLOCK: if (is_info_bank) /* Erasing the INFO bank from the RW section is * unsupported. */ return EC_ERROR_INVAL; opcode = 0x31415927; words = 0; /* don't care, really */ /* This number is based on the TSMC spec Nme=Terase/Tsme */ max_attempts = 45; break; case OP_WRITE_BLOCK: opcode = 0x27182818; words--; /* count register is zero-based */ /* This number is based on the TSMC spec Nmp=Tprog/Tsmp */ max_attempts = 9; break; case OP_READ_BLOCK: if (!is_info_bank) /* This code path only supports reading from * the INFO bank. */ return EC_ERROR_INVAL; opcode = 0x16021765; words = 1; max_attempts = 9; break; default: return EC_ERROR_INVAL; } /* * Set the parameters. For writes, we assume the write buffer is * already filled before we call this function. */ GWRITE_FIELD(FLASH, FSH_TRANS, OFFSET, byte_offset / 4); /* word offset */ GWRITE_FIELD(FLASH, FSH_TRANS, MAINB, is_info_bank ? 1 : 0); GWRITE_FIELD(FLASH, FSH_TRANS, SIZE, words); /* TODO: Make sure this function isn't getting called "too often" in * between erases. */ extra_prog_pulse = 0; for (retry_count = 0; retry_count < max_attempts; retry_count++) { /* Kick it off */ GWRITE(FLASH, FSH_PE_EN, 0xb11924e1); *fsh_pe_control = opcode; /* Wait for completion. 150ms should be enough * (crosbug.com/p/45366). */ for (i = 0; i < 1500; i++) { tmp = *fsh_pe_control; if (!tmp) break; usleep(timedelay_us); } /* Timed out waiting for control register to clear */ if (tmp) { CPRINTF("%s:%d\n", __func__, __LINE__); return EC_ERROR_UNKNOWN; } /* Check error status */ errors = GREAD(FLASH, FSH_ERROR); if (errors && (errors != prev_error)) { prev_error = errors; CPRINTF("%s:%d errors %x fsh_pe_control %p\n", __func__, __LINE__, errors, fsh_pe_control); } /* Error status is self-clearing. Read it until it does * (we hope). */ for (i = 0; i < 50; i++) { tmp = GREAD(FLASH, FSH_ERROR); if (!tmp) break; usleep(timedelay_us); } /* If we can't clear the error status register then something * is wrong. */ if (tmp) { CPRINTF("%s:%d\n", __func__, __LINE__); return EC_ERROR_UNKNOWN; } /* The operation was successful. */ if (!errors) { /* From the spec: * "In addition, one more program pulse is needed after * program verification is passed." */ if (op == OP_WRITE_BLOCK && !extra_prog_pulse) { extra_prog_pulse = 1; max_attempts++; continue; } return EC_SUCCESS; } /* If there were errors after completion retry. */ watchdog_reload(); } CPRINTF("%s:%d, retry count %d\n", __func__, __LINE__, retry_count); return EC_ERROR_UNKNOWN; }