static int crosec_spi_io(size_t req_size, size_t resp_size, void *context) { struct spi_slave *slave = (struct spi_slave *)context; spi_claim_bus(slave); /* Allow EC to ramp up clock after being awaken. * See chrome-os-partner:32223 for more details. */ udelay(CONFIG_EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US); if (spi_xfer(slave, req_buf, req_size, NULL, 0)) { printk(BIOS_ERR, "%s: Failed to send request.\n", __func__); spi_release_bus(slave); return -1; } uint8_t byte; struct stopwatch sw; // Wait 1s for a framing byte. stopwatch_init_usecs_expire(&sw, USECS_PER_SEC); while (1) { if (spi_xfer(slave, NULL, 0, &byte, sizeof(byte))) { printk(BIOS_ERR, "%s: Failed to receive byte.\n", __func__); spi_release_bus(slave); return -1; } if (byte == EcFramingByte) break; if (stopwatch_expired(&sw)) { printk(BIOS_ERR, "%s: Timeout waiting for framing byte.\n", __func__); spi_release_bus(slave); return -1; } } if (spi_xfer(slave, NULL, 0, resp_buf, resp_size)) { printk(BIOS_ERR, "%s: Failed to receive response.\n", __func__); spi_release_bus(slave); return -1; } spi_release_bus(slave); return 0; }
void greyScaleHack(uint8_t callNumber){ uint8_t x,colour,bits; spi_obtain_bus(1); pcdIO.assert_command(); pcdIO.assert_chip_delect(); spi_setup(SPI_DIVIDER_4, 0); //4 Mhz @ 16Mhz spi_io(PCD8544_CMD_SET_Y); spi_io(PCD8544_CMD_SET_X); pcdIO.desert_command(); colour=0; for (x=0; x<84; x++){ if (colour>callNumber) bits=0xff; else bits=0; spi_io(bits); spi_io(bits); spi_io(bits); spi_io(bits); spi_io(bits); spi_io(bits); if ((x&7)==0) colour++; colour &= 3; } pcdIO.desert_chip_select(); spi_release_bus(); }
static int sx151x_spi_read(int chip, unsigned char reg) { struct spi_slave *slave; int ret; slave = spi_setup_slave(CONFIG_SX151X_SPI_BUS, chip, 1000000, SPI_MODE_0); if (!slave) return 0; spi_claim_bus(slave); ret = spi_w8r8(slave, reg | 0x80); if (ret < 0) printf("spi%d.%d read fail: can't read %02x: %d\n", CONFIG_SX151X_SPI_BUS, chip, reg, ret); else printf("spi%d.%d read register 0x%02x: 0x%02x\n", CONFIG_SX151X_SPI_BUS, chip, reg, ret); spi_release_bus(slave); spi_free_slave(slave); return ret; }
/* * Initializes on-board ethernet controllers. */ int board_eth_init(bd_t *bis) { struct spi_slave *spi; const char *s; size_t len = 0; int config = 1; davinci_emac_mii_mode_sel(0); /* send a config file to the switch */ s = hwconfig_subarg("switch", "config", &len); if (len) { unsigned long addr = simple_strtoul(s, NULL, 16); config = enbw_cmc_config_switch(addr); } if (config) { /* * no valid config file -> do we have some args in * hwconfig ? */ if ((hwconfig_subarg("switch", "lan", &len)) || (hwconfig_subarg("switch", "lmn", &len))) { /* If so start switch */ spi = enbw_cmc_init_spi(); if (spi) { if (enbw_cmc_switch_write(spi, 1, 0)) config = 0; udelay(10000); if (enbw_cmc_switch_write(spi, 1, 1)) config = 0; spi_release_bus(spi); spi_free_slave(spi); } } else { config = 0; } } if (!davinci_emac_initialize()) { printf("Error: Ethernet init failed!\n"); return -1; } if (config) { if (hwconfig_subarg_cmp("switch", "lan", "on")) /* Switch port lan on */ enbw_cmc_switch(1, 1); else enbw_cmc_switch(1, 0); if (hwconfig_subarg_cmp("switch", "lmn", "on")) /* Switch port pwl on */ enbw_cmc_switch(2, 1); else enbw_cmc_switch(2, 0); } return 0; }
/** * spi_flash_probe_slave() - Probe for a SPI flash device on a bus * * @flashp: Pointer to place to put flash info, which may be NULL if the * space should be allocated */ static int spi_flash_probe_slave(struct spi_flash *flash) { struct spi_slave *spi = flash->spi; int ret; /* Setup spi_slave */ if (!spi) { printf("SF: Failed to set up slave\n"); return -ENODEV; } /* Claim spi bus */ ret = spi_claim_bus(spi); if (ret) { debug("SF: Failed to claim SPI bus: %d\n", ret); return ret; } ret = spi_nor_scan(flash); if (ret) goto err_read_id; #ifdef CONFIG_SPI_FLASH_MTD ret = spi_flash_mtd_register(flash); #endif err_read_id: spi_release_bus(spi); return ret; }
/* set clock time from *tmp in DS1306 RTC */ void rtc_set (struct rtc_time *tmp) { /* Assuming Vcc = 2.0V (lowest speed) */ if (!slave) { slave = spi_setup_slave(0, CFG_SPI_RTC_DEVID, 600000, SPI_MODE_3 | SPI_CS_HIGH); if (!slave) return; } if (spi_claim_bus(slave)) return; debug ("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); rtc_write (RTC_SECONDS, bin2bcd (tmp->tm_sec)); rtc_write (RTC_MINUTES, bin2bcd (tmp->tm_min)); rtc_write (RTC_HOURS, bin2bcd (tmp->tm_hour)); rtc_write (RTC_DAY_OF_WEEK, bin2bcd (tmp->tm_wday + 1)); rtc_write (RTC_DATE_OF_MONTH, bin2bcd (tmp->tm_mday)); rtc_write (RTC_MONTH, bin2bcd (tmp->tm_mon)); rtc_write (RTC_YEAR, bin2bcd (tmp->tm_year - 2000)); spi_release_bus(slave); }
int rtc_set(struct rtc_time *rtc) { u32 time, day, reg; if (!slave) { /* FIXME: Verify the max SCK rate */ slave = spi_setup_slave(CONFIG_MC13783_SPI_BUS, CONFIG_MC13783_SPI_CS, 1000000, SPI_MODE_2 | SPI_CS_HIGH); if (!slave) return -1; } time = mktime(rtc->tm_year, rtc->tm_mon, rtc->tm_mday, rtc->tm_hour, rtc->tm_min, rtc->tm_sec); day = time / 86400; time %= 86400; if (spi_claim_bus(slave)) return -1; reg = 0x2c000000 | day | 0x80000000; spi_xfer(slave, 32, (uchar *)®, (uchar *)&day, SPI_XFER_BEGIN | SPI_XFER_END); reg = 0x28000000 | time | 0x80000000; spi_xfer(slave, 32, (uchar *)®, (uchar *)&time, SPI_XFER_BEGIN | SPI_XFER_END); spi_release_bus(slave); return -1; }
static int enbw_cmc_config_switch(unsigned long addr) { struct spi_slave *spi; char *ptr = (char *)addr; int value, reg; int ret = 0; debug("configure switch with file on addr: 0x%lx\n", addr); spi = enbw_cmc_init_spi(); if (!spi) return -EINVAL; while (ptr != NULL) { ptr = enbw_cmc_getvalue(ptr, ®); if (ptr != NULL) { ptr = enbw_cmc_getvalue(ptr, &value); if ((ptr != NULL) && (value >= 0)) if (enbw_cmc_switch_write(spi, reg, value)) { /* error writing to switch */ ptr = NULL; ret = -EINVAL; } } } spi_release_bus(spi); spi_free_slave(spi); return ret; }
static int do_spi_xfer(int bus, int cs) { struct spi_slave *slave; int rcode = 0; slave = spi_setup_slave(bus, cs, 1000000, mode); if (!slave) { printf("Invalid device %d:%d\n", bus, cs); return -EINVAL; } spi_claim_bus(slave); if (spi_xfer(slave, bitlen, dout, din, SPI_XFER_BEGIN | SPI_XFER_END) != 0) { printf("Error during SPI transaction\n"); rcode = -EIO; } else { int j; for (j = 0; j < ((bitlen + 7) / 8); j++) printf("%02X", din[j]); printf("\n"); } spi_release_bus(slave); spi_free_slave(slave); return rcode; }
static struct spi_slave *enbw_cmc_init_spi(void) { struct spi_slave *spi; int ret; spi = spi_setup_slave(0, 0, 1000000, 0); if (!spi) { printf("Failed to set up slave\n"); return NULL; } ret = spi_claim_bus(spi); if (ret) { debug("Failed to claim SPI bus: %d\n", ret); goto err_claim_bus; } ret = enbw_cmc_switch_read_ident(spi); if (ret) goto err_read; return spi; err_read: spi_release_bus(spi); err_claim_bus: spi_free_slave(spi); return NULL; }
ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len) { struct spi_slave *slave; u8 cmd = SPI_EEPROM_READ; slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, 1, 1000000, CONFIG_DEFAULT_SPI_MODE); if (!slave) return 0; spi_claim_bus(slave); /* command */ if (spi_xfer(slave, 8, &cmd, NULL, SPI_XFER_BEGIN)) return -1; /* * if alen == 3, addr[0] is the block number, we never use it here. * All we need are the lower 16 bits. */ if (alen == 3) addr++; /* address, and data */ if (spi_xfer(slave, 16, addr, NULL, 0)) return -1; if (spi_xfer(slave, 8 * len, NULL, buffer, SPI_XFER_END)) return -1; spi_release_bus(slave); spi_free_slave(slave); return len; }
/* Test that sandbox SPI works correctly */ static int dm_test_spi_xfer(struct dm_test_state *dms) { struct spi_slave *slave; struct udevice *bus; const int busnum = 0, cs = 0, mode = 0; const char dout[5] = {0x9f}; unsigned char din[5]; ut_assertok(spi_get_bus_and_cs(busnum, cs, 1000000, mode, NULL, 0, &bus, &slave)); ut_assertok(spi_claim_bus(slave)); ut_assertok(spi_xfer(slave, 40, dout, din, SPI_XFER_BEGIN | SPI_XFER_END)); ut_asserteq(0xff, din[0]); ut_asserteq(0x20, din[1]); ut_asserteq(0x20, din[2]); ut_asserteq(0x15, din[3]); spi_release_bus(slave); /* * Since we are about to destroy all devices, we must tell sandbox * to forget the emulation device */ #ifdef CONFIG_DM_SPI_FLASH sandbox_sf_unbind_emul(state_get_current(), busnum, cs); #endif return 0; }
int cros_ec_spi_packet(struct udevice *udev, int out_bytes, int in_bytes) { struct cros_ec_dev *dev = dev_get_uclass_priv(udev); struct spi_slave *slave = dev_get_parentdata(dev->dev); int rv; /* Do the transfer */ if (spi_claim_bus(slave)) { debug("%s: Cannot claim SPI bus\n", __func__); return -1; } rv = spi_xfer(slave, max(out_bytes, in_bytes) * 8, dev->dout, dev->din, SPI_XFER_BEGIN | SPI_XFER_END); spi_release_bus(slave); if (rv) { debug("%s: Cannot complete SPI transfer\n", __func__); return -1; } return in_bytes; }
static int lq035q1_control(unsigned char reg, unsigned short value) { int ret; u8 regs[3] = {LQ035_INDEX, 0, 0}; u8 data[3] = {LQ035_DATA, 0, 0}; u8 dummy[3]; regs[2] = reg; data[1] = value >> 8; data[2] = value & 0xFF; if (!slave) { /* FIXME: Verify the max SCK rate */ slave = spi_setup_slave(CONFIG_LQ035Q1_SPI_BUS, CONFIG_LQ035Q1_SPI_CS, 20000000, SPI_MODE_3); if (!slave) return -1; } if (spi_claim_bus(slave)) return -1; ret = spi_xfer(slave, 24, regs, dummy, SPI_XFER_BEGIN | SPI_XFER_END); ret |= spi_xfer(slave, 24, data, dummy, SPI_XFER_BEGIN | SPI_XFER_END); spi_release_bus(slave); return ret; }
/* reset the DS1306 */ void rtc_reset (void) { /* Assuming Vcc = 2.0V (lowest speed) */ if (!slave) { slave = spi_setup_slave(0, CFG_SPI_RTC_DEVID, 600000, SPI_MODE_3 | SPI_CS_HIGH); if (!slave) return; } if (spi_claim_bus(slave)) return; /* clear the control register */ rtc_write (RTC_CONTROL, 0x00); /* 1st step: reset WP */ rtc_write (RTC_CONTROL, 0x00); /* 2nd step: reset 1Hz, AIE1, AIE0 */ /* reset all alarms */ rtc_write (RTC_SECONDS_ALARM0, 0x00); rtc_write (RTC_SECONDS_ALARM1, 0x00); rtc_write (RTC_MINUTES_ALARM0, 0x00); rtc_write (RTC_MINUTES_ALARM1, 0x00); rtc_write (RTC_HOURS_ALARM0, 0x00); rtc_write (RTC_HOURS_ALARM1, 0x00); rtc_write (RTC_DAY_OF_WEEK_ALARM0, 0x00); rtc_write (RTC_DAY_OF_WEEK_ALARM1, 0x00); spi_release_bus(slave); }
void spi_SaveS3info(u32 pos, u32 size, u8 *buf, u32 len) { struct spi_flash *flash; spi_init(); flash = spi_flash_probe(0, 0); if (!flash) { printk(BIOS_DEBUG, "Could not find SPI device\n"); /* Dont make flow stop. */ return; } flash->spi->rw = SPI_WRITE_FLAG; spi_claim_bus(flash->spi); flash->erase(flash, pos, size); flash->write(flash, pos, sizeof(len), &len); u32 nvram_pos; for (nvram_pos = 0; nvram_pos < len - CONFIG_AMD_SB_SPI_TX_LEN; nvram_pos += CONFIG_AMD_SB_SPI_TX_LEN) { flash->write(flash, nvram_pos + pos + 4, CONFIG_AMD_SB_SPI_TX_LEN, (u8 *)(buf + nvram_pos)); } flash->write(flash, nvram_pos + pos + 4, len % CONFIG_AMD_SB_SPI_TX_LEN, (u8 *)(buf + nvram_pos)); flash->spi->rw = SPI_WRITE_FLAG; spi_release_bus(flash->spi); return; }
static int sx151x_spi_write(int chip, unsigned char reg, unsigned char val) { struct spi_slave *slave; unsigned char buf[2]; int ret; slave = spi_setup_slave(CONFIG_SX151X_SPI_BUS, chip, 1000000, SPI_MODE_0); if (!slave) return 0; spi_claim_bus(slave); buf[0] = reg; buf[1] = val; ret = spi_xfer(slave, 16, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END); if (ret < 0) printf("spi%d.%d write fail: can't write %02x to %02x: %d\n", CONFIG_SX151X_SPI_BUS, chip, val, reg, ret); else printf("spi%d.%d write 0x%02x to register 0x%02x\n", CONFIG_SX151X_SPI_BUS, chip, val, reg); spi_release_bus(slave); spi_free_slave(slave); return ret; }
static u32 pmic_reg(struct pmic *p, u32 reg, u32 *val, u32 write) { u32 pmic_tx, pmic_rx; u32 tmp; if (!slave) { slave = spi_setup_slave(p->bus, p->hw.spi.cs, p->hw.spi.clk, p->hw.spi.mode); if (!slave) return -ENODEV; } if (check_reg(p, reg)) return -EINVAL; if (spi_claim_bus(slave)) return -EBUSY; pmic_tx = p->hw.spi.prepare_tx(reg, val, write); tmp = cpu_to_be32(pmic_tx); if (spi_xfer(slave, pmic_spi_bitlen, &tmp, &pmic_rx, pmic_spi_flags)) goto err; if (write) { pmic_tx = p->hw.spi.prepare_tx(reg, val, 0); tmp = cpu_to_be32(pmic_tx); if (spi_xfer(slave, pmic_spi_bitlen, &tmp, &pmic_rx, pmic_spi_flags)) goto err; } spi_release_bus(slave); *val = cpu_to_be32(pmic_rx); return 0; err: spi_release_bus(slave); return -ENOTSUPP; }
u32 OemAgesaSaveS3Info(S3_DATA_TYPE S3DataType, u32 DataSize, void *Data) { u32 pos; struct spi_flash *flash; u8 *new_data; u32 bytes_to_process; u32 nvram_pos; if (S3DataType == S3DataTypeNonVolatile) pos = S3_DATA_NONVOLATILE_POS; else pos = S3_DATA_VOLATILE_POS; spi_init(); flash = spi_flash_probe(0, 0, 0, 0); if (!flash) { printk(BIOS_DEBUG, "%s: Could not find SPI device\n", __func__); /* Don't make flow stop. */ return AGESA_SUCCESS; } flash->spi->rw = SPI_WRITE_FLAG; spi_claim_bus(flash->spi); // initialize the incoming data array new_data = (u8 *)malloc(DataSize + (u32)sizeof(DataSize)); memcpy(new_data, &DataSize, (u32)sizeof(DataSize)); // the size gets written first memcpy(new_data + (u32)sizeof(DataSize), Data, DataSize); DataSize += (u32)sizeof(DataSize); // add in the size of the data for ( ; DataSize > 0; DataSize -= bytes_to_process) { bytes_to_process = ( DataSize >= flash->sector_size) ? flash->sector_size : DataSize; if (memcmp((u8 *)pos, (u8 *)new_data, bytes_to_process)) { printk(BIOS_DEBUG, "%s: Data mismatch - write the data\n", __func__); flash->erase(flash, pos, flash->sector_size); for (nvram_pos = 0; \ nvram_pos < bytes_to_process - (bytes_to_process % CONFIG_AMD_SB_SPI_TX_LEN); \ nvram_pos += CONFIG_AMD_SB_SPI_TX_LEN) { flash->write(flash, pos + nvram_pos, CONFIG_AMD_SB_SPI_TX_LEN, \ (u8 *)(new_data + nvram_pos)); } flash->write(flash, pos + nvram_pos, bytes_to_process % CONFIG_AMD_SB_SPI_TX_LEN, \ (u8 *)(new_data + nvram_pos)); } else printk(BIOS_DEBUG, "%s: existing nvram data matched\n", __func__); new_data += bytes_to_process; pos += bytes_to_process; } free(new_data); flash->spi->rw = SPI_WRITE_FLAG; spi_release_bus(flash->spi); return AGESA_SUCCESS; }
int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len) { int ret; spi_claim_bus(spi); ret = spi_aml_cmd(spi, &cmd, len*8, NULL,response, 0); spi_release_bus(spi); return ret; }
static int mmc_spi_init_p(struct mmc *mmc) { struct spi_slave *spi = mmc->priv; spi_set_speed(spi, MMC_SPI_MIN_CLOCK); spi_claim_bus(spi); /* cs deactivated for 100+ clock */ spi_xfer(spi, 18 * 8, NULL, NULL, 0); spi_release_bus(spi); return 0; }
static u32 pmic_reg(struct pmic *p, u32 reg, u32 *val, u32 write) { u32 pmic_tx, pmic_rx; u32 tmp; if (!slave) { slave = pmic_spi_probe(p); if (!slave) return -1; } if (check_reg(p, reg)) return -1; if (spi_claim_bus(slave)) return -1; pmic_tx = p->hw.spi.prepare_tx(reg, val, write); tmp = cpu_to_be32(pmic_tx); if (spi_xfer(slave, pmic_spi_bitlen, &tmp, &pmic_rx, pmic_spi_flags)) { spi_release_bus(slave); return -1; } if (write) { pmic_tx = p->hw.spi.prepare_tx(reg, val, 0); tmp = cpu_to_be32(pmic_tx); if (spi_xfer(slave, pmic_spi_bitlen, &tmp, &pmic_rx, pmic_spi_flags)) { spi_release_bus(slave); return -1; } } spi_release_bus(slave); *val = cpu_to_be32(pmic_rx); return 0; }
/* * To write a register, start transaction, transfer data to the TPM, deassert * CS when done. * * Returns one to indicate success, zero to indicate failure. */ static int tpm2_write_reg(unsigned reg_number, const void *buffer, size_t bytes) { struct spi_slave *spi_slave = car_get_var_ptr(&g_spi_slave); trace_dump("W", reg_number, bytes, buffer, 0); if (!start_transaction(false, bytes, reg_number)) return 0; write_bytes(buffer, bytes); spi_release_bus(spi_slave); return 1; }
int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, size_t cmd_len, void *data, size_t data_len) { struct spi_slave *spi = flash->spi; int ret; spi_claim_bus(spi); ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); spi_release_bus(spi); return ret; }
int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, const void *data, size_t data_len) { int ret; spi_claim_bus(spi); ret = spi_aml_cmd(spi, cmd, data_len, data,NULL, SPI_CMD_HAS_ADDR); spi_release_bus(spi); return ret; }
/* * To read a register, start transaction, transfer data from the TPM, deassert * CS when done. * * Returns one to indicate success, zero to indicate failure. In case of * failure zero out the user buffer. */ static int tpm2_read_reg(unsigned reg_number, void *buffer, size_t bytes) { struct spi_slave *spi_slave = car_get_var_ptr(&g_spi_slave); if (!start_transaction(true, bytes, reg_number)) { memset(buffer, 0, bytes); return 0; } read_bytes(buffer, bytes); spi_release_bus(spi_slave); trace_dump("R", reg_number, bytes, buffer, 0); return 1; }
u32 pmic_reg(u32 reg, u32 val, u32 write) { u32 pmic_tx, pmic_rx; if (!slave) { slave = pmic_spi_probe(); if (!slave) return -1; } if (reg > 63 || write > 1) { printf("<reg num> = %d is invalid. Should be less then 63\n", reg); return -1; } if (spi_claim_bus(slave)) return -1; pmic_tx = (write << 31) | (reg << 25) | (val & 0x00FFFFFF); if (spi_xfer(slave, 4 << 3, &pmic_tx, &pmic_rx, SPI_XFER_BEGIN | SPI_XFER_END)) { spi_release_bus(slave); return -1; } if (write) { pmic_tx &= ~(1 << 31); if (spi_xfer(slave, 4 << 3, &pmic_tx, &pmic_rx, SPI_XFER_BEGIN | SPI_XFER_END)) { spi_release_bus(slave); return -1; } } spi_release_bus(slave); return pmic_rx; }
static void amoled_write_spi_command(struct spi_slave *spi, unsigned char command, unsigned char arg) { unsigned char spi_cmd[2]; spi_cmd[0] = command; spi_cmd[1] = arg; /* SPI_MODE_1 (clk active high) */ spi_claim_bus(spi); spi_xfer(spi, 8*2, spi_cmd, NULL, 0); spi_release_bus(spi); }
int rtc_get(struct rtc_time *rtc) { u32 day1, day2, time; u32 reg; int err, tim, i = 0; if (!slave) { /* FIXME: Verify the max SCK rate */ slave = spi_setup_slave(CONFIG_MC13783_SPI_BUS, CONFIG_MC13783_SPI_CS, 1000000, SPI_MODE_2 | SPI_CS_HIGH); if (!slave) return -1; } if (spi_claim_bus(slave)) return -1; do { reg = 0x2c000000; err = spi_xfer(slave, 32, (uchar *)®, (uchar *)&day1, SPI_XFER_BEGIN | SPI_XFER_END); if (err) return err; reg = 0x28000000; err = spi_xfer(slave, 32, (uchar *)®, (uchar *)&time, SPI_XFER_BEGIN | SPI_XFER_END); if (err) return err; reg = 0x2c000000; err = spi_xfer(slave, 32, (uchar *)®, (uchar *)&day2, SPI_XFER_BEGIN | SPI_XFER_END); if (err) return err; } while (day1 != day2 && i++ < 3); spi_release_bus(slave); tim = day1 * 86400 + time; to_tm(tim, rtc); rtc->tm_yday = 0; rtc->tm_isdst = 0; return 0; }
ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len) { struct spi_slave *slave; char buf[3]; ulong start; slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, 1, 1000000, CONFIG_DEFAULT_SPI_MODE); if (!slave) return 0; spi_claim_bus(slave); buf[0] = SPI_EEPROM_WREN; if (spi_xfer(slave, 8, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END)) return -1; buf[0] = SPI_EEPROM_WRITE; /* As for reading, drop addr[0] if alen is 3 */ if (alen == 3) { alen--; addr++; } memcpy(buf + 1, addr, alen); /* command + addr, then data */ if (spi_xfer(slave, 24, buf, NULL, SPI_XFER_BEGIN)) return -1; if (spi_xfer(slave, len * 8, buffer, NULL, SPI_XFER_END)) return -1; start = get_timer(0); do { buf[0] = SPI_EEPROM_RDSR; buf[1] = 0; spi_xfer(slave, 16, buf, buf, SPI_XFER_BEGIN | SPI_XFER_END); if (!(buf[1] & 1)) break; } while (get_timer(start) < CONFIG_SYS_SPI_WRITE_TOUT); if (buf[1] & 1) printf("*** spi_write: Timeout while writing!\n"); spi_release_bus(slave); spi_free_slave(slave); return len; }