static int cxd2880_spi_read_ts(struct spi_device *spi, u8 *read_data, u32 packet_num) { int ret; u8 data[3]; struct spi_message message; struct spi_transfer transfer[2] = {}; if (!spi || !read_data || !packet_num) { pr_err("invalid arg\n"); return -EINVAL; } if (packet_num > 0xffff) { pr_err("packet num > 0xffff\n"); return -EINVAL; } data[0] = 0x10; data[1] = packet_num >> 8; data[2] = packet_num; spi_message_init(&message); transfer[0].len = 3; transfer[0].tx_buf = data; spi_message_add_tail(&transfer[0], &message); transfer[1].len = packet_num * 188; transfer[1].rx_buf = read_data; spi_message_add_tail(&transfer[1], &message); ret = spi_sync(spi, &message); if (ret) pr_err("spi_write_then_read failed\n"); return ret; }
static int smt113j_spi_cmd_init ( void ) { int ret = 0; ioctl_spi_internal_reg spi_command = { 0 }; struct spi_message m = {{ 0 }}; struct spi_transfer t[3] = {{ 0 }}; DEBUG_PRINT("smt113j_spi_cmd_init << Start >>"); /*** SPI message init ***/ spi_message_init ( &m ); /*** SPI command set ***/ spi_command.cmd = 0x01; spi_command.data = 0xB1; /*** transfer data set ***/ t[0].tx_buf = &spi_command; t[0].rx_buf = NULL; t[0].len = sizeof ( spi_command ); spi_message_add_tail ( &t[0], &m ); /*** SPI transfer request ***/ ret = spi_sync ( smt113j_spi_device, &m ); if ( 0 > ret ) { ERROR_PRINT ("smt113j_spi_cmd_init : Sync Error << ret = %d >>", ret ); } DEBUG_PRINT("smt113j_spi_cmd_init << End : %d >>", ret ); return ( ret ); }
/** * adis16203_read_ring_data() read data registers which will be placed into ring * @indio_dev: the IIO device * @rx: somewhere to pass back the value read **/ static int adis16203_read_ring_data(struct iio_dev *indio_dev, u8 *rx) { struct spi_message msg; struct adis16203_state *st = iio_priv(indio_dev); struct spi_transfer xfers[ADIS16203_OUTPUTS + 1]; int ret; int i; mutex_lock(&st->buf_lock); spi_message_init(&msg); memset(xfers, 0, sizeof(xfers)); for (i = 0; i <= ADIS16203_OUTPUTS; i++) { xfers[i].bits_per_word = 8; xfers[i].cs_change = 1; xfers[i].len = 2; xfers[i].delay_usecs = 20; xfers[i].tx_buf = st->tx + 2 * i; if (i < 1) /* SUPPLY_OUT: 0x02, AUX_ADC: 0x08 */ st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i); else st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i + 6); st->tx[2 * i + 1] = 0; if (i >= 1) xfers[i].rx_buf = rx + 2 * (i - 1); spi_message_add_tail(&xfers[i], &msg); } ret = spi_sync(st->us, &msg); if (ret) dev_err(&st->us->dev, "problem when burst reading"); mutex_unlock(&st->buf_lock); return ret; }
static int smt113j_spi_cmd_pktsync ( void ) { int ret = 0; ioctl_spi_pktsync spi_command = { 0 }; struct spi_message m = {{ 0 }}; struct spi_transfer t[3] = {{ 0 }}; /*** SPI message init ***/ spi_message_init ( &m ); /*** SPI command set ***/ spi_command.cmd = 0xD8; spi_command.dum1 = 0x00; spi_command.dum2 = 0x00; spi_command.dum3 = 0x00; /*** transfer data set ***/ t[0].tx_buf = &spi_command; t[0].rx_buf = NULL; t[0].len = sizeof ( spi_command ); spi_message_add_tail ( &t[0], &m ); /*** SPI transfer request ***/ ret = spi_sync ( smt113j_spi_device, &m ); if ( 0 > ret ) { ERROR_PRINT ("smt113j_spi_cmd_pktsync : Sync Error << ret = %d >>", ret ); } printk("smt113j_spi_cmd_pktsync << End : %d >>\n", ret ); return ( ret ); }
int touch_spi_xfer(struct spi_device *spi, struct touch_xfer_msg *xfer) { struct touch_xfer_data_t *tx = NULL; struct touch_xfer_data_t *rx = NULL; struct spi_transfer x[MAX_XFER_COUNT]; struct spi_message m; int i = 0; if (xfer->msg_count > MAX_XFER_COUNT) { TOUCH_E("cout exceed\n"); return -1; } spi_message_init(&m); memset(x, 0, sizeof(x)); for (i = 0; i < xfer->msg_count; i++) { tx = &xfer->data[i].tx; rx = &xfer->data[i].rx; x[i].cs_change = 1; x[i].bits_per_word = xfer->bits_per_word; if (rx->size) { x[i].tx_buf = tx->data; x[i].rx_buf = rx->data; x[i].len = rx->size; } else { x[i].tx_buf = tx->data; x[i].rx_buf = NULL; x[i].len = tx->size; } spi_message_add_tail(&x[i], &m); } return spi_sync(spi, &m); }
static int epm_psoc_set_averaging(struct epm_adc_drv *epm_adc, struct epm_psoc_set_avg *psoc_set_avg) { struct spi_message m; struct spi_transfer t; char tx_buf[4], rx_buf[4]; int rc = 0; spi_setup(epm_adc->epm_spi_client); memset(&t, 0, sizeof t); memset(tx_buf, 0, sizeof tx_buf); memset(rx_buf, 0, sizeof tx_buf); t.tx_buf = tx_buf; t.rx_buf = rx_buf; spi_message_init(&m); spi_message_add_tail(&t, &m); tx_buf[0] = psoc_set_avg->cmd; tx_buf[1] = psoc_set_avg->avg_period; t.len = sizeof(tx_buf); t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD; rc = spi_sync(epm_adc->epm_spi_client, &m); if (rc) return rc; rc = spi_sync(epm_adc->epm_spi_client, &m); if (rc) return rc; psoc_set_avg->cmd = rx_buf[0]; psoc_set_avg->return_code = rx_buf[1]; return rc; }
static int corgi_ssp_lcdtg_send(struct corgi_lcd *lcd, int adrs, uint8_t data) { struct spi_message msg; struct spi_transfer xfer = { .len = 1, .cs_change = 1, .tx_buf = lcd->buf, }; lcd->buf[0] = ((adrs & 0x07) << 5) | (data & 0x1f); spi_message_init(&msg); spi_message_add_tail(&xfer, &msg); return spi_sync(lcd->spi_dev, &msg); } /* Set Phase Adjust */ static void lcdtg_set_phadadj(struct corgi_lcd *lcd, int mode) { int adj; switch (mode) { case CORGI_LCD_MODE_VGA: /* Setting for VGA */ adj = sharpsl_param.phadadj; adj = (adj < 0) ? PHACTRL_PHASE_MANUAL : PHACTRL_PHASE_MANUAL | ((adj & 0xf) << 1); break; case CORGI_LCD_MODE_QVGA: default: /* Setting for QVGA */ adj = (DEFAULT_PHAD_QVGA << 1) | PHACTRL_PHASE_MANUAL; break; } corgi_ssp_lcdtg_send(lcd, PHACTRL_ADRS, adj); }
static int bu21150_write_register(u32 addr, u16 size, u8 *data) { struct bu21150_data *ts = spi_get_drvdata(g_client_bu21150); struct spi_device *client = ts->client; struct ser_req *req; int ret; u8 *input; input = kzalloc(sizeof(u8)*(size)+SPI_HEADER_SIZE, GFP_KERNEL); req = kzalloc(sizeof(*req), GFP_KERNEL); /* set header */ input[0] = 0x02; /* write command */ input[1] = (addr & 0xFF00) >> 8; /* address hi */ input[2] = (addr & 0x00FF) >> 0; /* address lo */ /* set data */ memcpy(input+SPI_HEADER_SIZE, data, size); swap_2byte(input+SPI_HEADER_SIZE, size); /* write data */ spi_message_init(&req->msg); req->xfer[0].tx_buf = input; req->xfer[0].rx_buf = NULL; req->xfer[0].len = size+SPI_HEADER_SIZE; req->xfer[0].cs_change = 0; req->xfer[0].bits_per_word = SPI_BITS_PER_WORD_WRITE; spi_message_add_tail(&req->xfer[0], &req->msg); ret = spi_sync(client, &req->msg); if (ret) pr_err("%s : spi_sync read data error:ret=[%d]", __func__, ret); kfree(req); kfree(input); return ret; }
int fc8050_spi_write_then_read(struct spi_device *spi, fci_u8 *txbuf, fci_u16 tx_length, fci_u8 *rxbuf, fci_u16 rx_length) { fci_s32 res; struct spi_message message; struct spi_transfer x; spi_message_init(&message); memset(&x, 0, sizeof x); spi_message_add_tail(&x, &message); memcpy(tdata_buf, txbuf, tx_length); x.tx_buf=tdata_buf; x.rx_buf=rdata_buf; x.len = tx_length + rx_length; res = spi_sync(spi, &message); memcpy(rxbuf, x.rx_buf + tx_length, rx_length); return res; }
int linux_spi_write(uint8_t *b, uint32_t len) { int ret; struct spi_message msg; if (len > 0 && NULL != b) { struct spi_transfer tr = { .tx_buf = b, .len = len, .speed_hz = SPEED, .delay_usecs = 0, }; char *r_buffer = kzalloc(len, GFP_KERNEL); if (!r_buffer) return 0; /* TODO: it should be return -ENOMEM */ tr.rx_buf = r_buffer; PRINT_D(BUS_DBG, "Request writing %d bytes\n", len); spi_message_init(&msg); spi_message_add_tail(&tr, &msg); ret = spi_sync(wilc_spi_dev, &msg); if (ret < 0) PRINT_ER("SPI transaction failed\n"); kfree(r_buffer); } else { PRINT_ER("can't write data due to NULL buffer or zero length\n"); ret = -1; } (ret < 0) ? (ret = 0) : (ret = 1); return ret; }
static int __nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb, int cs_change) { struct spi_message m; struct spi_transfer t; memset(&t, 0, sizeof(struct spi_transfer)); /* a NULL skb means we just want the SPI chip select line to raise */ if (skb) { t.tx_buf = skb->data; t.len = skb->len; } else { /* still set tx_buf non NULL to make the driver happy */ t.tx_buf = &t; t.len = 0; } t.cs_change = cs_change; t.delay_usecs = nspi->xfer_udelay; spi_message_init(&m); spi_message_add_tail(&t, &m); return spi_sync(nspi->spi, &m); }
/** * ili922x_read_status - read status register from display * @spi: spi device * @rs: output value */ static int ili922x_read_status(struct spi_device *spi, u16 *rs) { struct spi_message msg; struct spi_transfer xfer; unsigned char tbuf[CMD_BUFSIZE]; unsigned char rbuf[CMD_BUFSIZE]; int ret, i; memset(&xfer, 0, sizeof(struct spi_transfer)); spi_message_init(&msg); xfer.tx_buf = tbuf; xfer.rx_buf = rbuf; xfer.cs_change = 1; CHECK_FREQ_REG(spi, &xfer); tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX, START_RW_READ)); /* * we need 4-byte xfer here due to invalid dummy byte * received after start byte */ for (i = 1; i < 4; i++) tbuf[i] = set_tx_byte(0); /* dummy */ xfer.bits_per_word = 8; xfer.len = 4; spi_message_add_tail(&xfer, &msg); ret = spi_sync(spi, &msg); if (ret < 0) { dev_dbg(&spi->dev, "Error sending SPI message 0x%x", ret); return ret; } *rs = (rbuf[2] << 8) + rbuf[3]; return 0; }
int kxr94_spi_write( struct spi_device *spi_dev, unsigned char addr, unsigned char data ) { unsigned char tx_buf[2]={addr, data}; struct spi_message msg; struct spi_transfer transfer; int retval; /* Prepare the data. */ memset( &msg, 0, sizeof( msg ) ); memset( &transfer, 0, sizeof( transfer ) ); spi_message_init( &msg ); /* Prepare the address cycle. */ transfer.tx_buf=tx_buf; transfer.len=sizeof( tx_buf ); transfer.delay_usecs=80; spi_message_add_tail( &transfer, &msg ); /* Finalize and transmit. */ msg.spi=spi_dev; msg.is_dma_mapped=0; retval=spi_sync( spi_dev, &msg ); return retval; }
static int max6902_get_reg(struct device *dev, unsigned char address, unsigned char *data) { struct spi_device *spi = to_spi_device(dev); struct max6902 *chip = dev_get_drvdata(dev); struct spi_message message; struct spi_transfer xfer; int status; if (!data) return -EINVAL; /* Build our spi message */ spi_message_init(&message); memset(&xfer, 0, sizeof(xfer)); xfer.len = 2; /* Can tx_buf and rx_buf be equal? The doc in spi.h is not sure... */ xfer.tx_buf = chip->tx_buf; xfer.rx_buf = chip->rx_buf; /* Set MSB to indicate read */ chip->tx_buf[0] = address | 0x80; spi_message_add_tail(&xfer, &message); /* do the i/o */ status = spi_sync(spi, &message); if (status == 0) status = message.status; else return status; *data = chip->rx_buf[1]; return status; }
int ab4500_read(struct ab4500 *ab4500, unsigned char block, unsigned long addr) { struct spi_transfer xfer; struct spi_message msg; unsigned long spi_data = 1 << 23 | block << 18 | addr << 10; mutex_lock(&ab4500->lock); ab4500->tx_buf[0] = spi_data; ab4500->rx_buf[0] = 0; xfer.tx_buf = ab4500->tx_buf; xfer.rx_buf = ab4500->rx_buf; xfer.len = sizeof(unsigned long); spi_message_init(&msg); spi_message_add_tail(&xfer, &msg); spi_sync(ab4500->spi, &msg); mutex_unlock(&ab4500->lock); return ab4500->rx_buf[0]; }
static int max3110_write_then_read(struct uart_max3110 *max, const void *txbuf, void *rxbuf, unsigned len, int always_fast) { struct spi_device *spi = max->spi; struct spi_message message; struct spi_transfer x; int ret; spi_message_init(&message); memset(&x, 0, sizeof x); x.len = len; x.tx_buf = txbuf; x.rx_buf = rxbuf; spi_message_add_tail(&x, &message); if (always_fast) x.speed_hz = spi->max_speed_hz; else if (max->baud) x.speed_hz = max->baud; /* Do the i/o */ ret = spi_sync(spi, &message); return ret; }
int mc13783_reg_read(struct mc13783 *mc13783, unsigned int offset, u32 *val) { struct spi_transfer t; struct spi_message m; int ret; BUG_ON(!mutex_is_locked(&mc13783->lock)); if (offset > MC13783_NUMREGS) return -EINVAL; *val = offset << MC13783_REGOFFSET_SHIFT; memset(&t, 0, sizeof(t)); t.tx_buf = val; t.rx_buf = val; t.len = sizeof(u32); spi_message_init(&m); spi_message_add_tail(&t, &m); ret = spi_sync(mc13783->spidev, &m); /* error in message.status implies error return from spi_sync */ BUG_ON(!ret && m.status); if (ret) return ret; *val &= 0xffffff; dev_vdbg(&mc13783->spidev->dev, "[0x%02x] -> 0x%06x\n", offset, *val); return 0; }
int linux_spi_read(unsigned char*rb, unsigned long rlen){ int ret; if(rlen > 0){ struct spi_message msg; struct spi_transfer tr = { // .tx_buf = t_buffer, .rx_buf = rb, .len = rlen, .speed_hz = SPEED, .delay_usecs = 0, }; char *t_buffer = (char*) kzalloc(rlen, GFP_KERNEL); if(! t_buffer){ PRINT_ER("Failed to allocate memory for t_buffer\n"); } tr.tx_buf = t_buffer; spi_message_init(&msg); spi_message_add_tail(&tr,&msg); ret = spi_sync(atwilc_spi_dev,&msg); if(ret < 0){ PRINT_ER("SPI transaction failed\n"); } kfree(t_buffer); }else{ PRINT_ER("can't read data with the following length: %ld\n",rlen); ret = -1; } /* change return value to match ATWILC interface */ (ret<0)? (ret = 0):(ret = 1); return ret; }
static int spi_rw(struct spi_device *spi, void * buf, size_t len) { int ret; struct spi_transfer t = { .tx_buf = (const void *)buf, .rx_buf = buf, .len = len, .cs_change = 0, .delay_usecs = 0, }; struct spi_message m; spi_message_init(&m); spi_message_add_tail(&t, &m); if ((ret = spi_sync(spi, &m))) return ret; return 0; } #define MXC_PMIC_REG_NUM(reg) (((reg) & 0x3f) << 25) #define MXC_PMIC_WRITE (1 << 31) static int mc13892_spi_reg_read(struct mc13892 *mc13892, enum mc13892_reg reg, u32 *val) { uint32_t buf; buf = MXC_PMIC_REG_NUM(reg); spi_rw(mc13892->spi, &buf, 4); *val = buf; return 0; }
static int __must_check wl12xx_spi_raw_read(struct device *child, int addr, void *buf, size_t len, bool fixed) { struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); struct wl1271 *wl = dev_get_drvdata(child); struct spi_transfer t[2]; struct spi_message m; u32 *busy_buf; u32 *cmd; u32 chunk_len; while (len > 0) { chunk_len = min_t(size_t, WSPI_MAX_CHUNK_SIZE, len); cmd = &wl->buffer_cmd; busy_buf = wl->buffer_busyword; *cmd = 0; *cmd |= WSPI_CMD_READ; *cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; *cmd |= addr & WSPI_CMD_BYTE_ADDR; if (fixed) *cmd |= WSPI_CMD_FIXED; spi_message_init(&m); memset(t, 0, sizeof(t)); t[0].tx_buf = cmd; t[0].len = 4; t[0].cs_change = true; spi_message_add_tail(&t[0], &m); /* Busy and non busy words read */ t[1].rx_buf = busy_buf; t[1].len = WL1271_BUSY_WORD_LEN; t[1].cs_change = true; spi_message_add_tail(&t[1], &m); spi_sync(to_spi_device(glue->dev), &m); if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && wl12xx_spi_read_busy(child)) { memset(buf, 0, chunk_len); return 0; } spi_message_init(&m); memset(t, 0, sizeof(t)); t[0].rx_buf = buf; t[0].len = chunk_len; t[0].cs_change = true; spi_message_add_tail(&t[0], &m); spi_sync(to_spi_device(glue->dev), &m); if (!fixed) addr += chunk_len; buf += chunk_len; len -= chunk_len; } return 0; }
static ssize_t sq_spi_download_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { int err = 0; //char *p; struct spi_message msg; struct spi_transfer xfer; //char buf[128]; char *buf; buf = kmalloc(len,GFP_KERNEL); if(!buf) { return -ENOMEM; } if(copy_from_user(buf,data,len)) { return -EFAULT; } SPI_DOWNLOAD_DBG(" write len=0x%x =>",len); #if (SPI_CTRL_GPIO_EN == 1 ) do { #endif /* i=0; while(1) { sq_gpio_set_low(TST_GPIO_G,1<<i); sq_gpio_set_high(TST_GPIO_G,1<<i); i++; if(i>0x07) i=0; } */ #if 0 i=1; while(i--) { sq_gpio_set_low(TST_GPIO_G,DL_PROGB); udelay(20); sq_gpio_set_high(TST_GPIO_G,DL_PROGB); /* sq_gpio_set_low(TST_GPIO_G,DL_RST); udelay(20); sq_gpio_set_high(TST_GPIO_G,DL_RST); sq_gpio_set_low(TST_GPIO_G,DL_INITB); udelay(20); sq_gpio_set_high(TST_GPIO_G,DL_INITB); sq_gpio_set_low(TST_GPIO_G,DL_DONE); udelay(20); sq_gpio_set_high(TST_GPIO_G,DL_DONE); */ //sq_gpio_in(TST_GPIO_G,DL_INITB); //sq_gpio_in(TST_GPIO_G,DL_DONE); //sq_spi_download_write_rst(); } #endif /* c = len; p = data; while(c--) { printk("%c",*p++); } printk("\n"); */ #if 1 spi_message_init(&msg); memset(&xfer, 0, sizeof(struct spi_transfer)); //SPI_DOWNLOAD_DBG(" bits_per_word= %d",msg.spi->bits_per_word); xfer.tx_buf = buf; // xfer.tx_buf = tx_buf; xfer.len = SET_TX_RX_LEN(len, 0); spi_message_add_tail(&xfer, &msg); #if (SPI_CTRL_GPIO_EN == 1 ) sq_spi_download_write_before(); #endif err = spi_sync(sq_spi_download_device, &msg); #if (SPI_CTRL_GPIO_EN == 1 ) //sq_spi_download_write_chk(); } while (sq_spi_download_write_chk() != 0 ); #endif #endif kfree(buf); // SPI_DOWNLOAD_DBG(" <============== sq_spi_download_write end ===============>"); return 0; }
static int ak4182_read12_ser(struct device *dev, unsigned command) { struct spi_device *spi = to_spi_device(dev); struct ak4182 *ts = dev_get_drvdata(dev); struct ser_req *req = kzalloc(sizeof *req, GFP_KERNEL); int status; int sample; int use_internal; if (!req) return -ENOMEM; spi_message_init(&req->msg); /* FIXME boards with ak4182 might use external vref instead ... */ use_internal = (ts->model == 4182); /* maybe turn on internal vREF, and let it settle */ if (use_internal) { req->ref_on = REF_ON; req->xfer[0].tx_buf = &req->ref_on; req->xfer[0].len = 1; spi_message_add_tail(&req->xfer[0], &req->msg); req->xfer[1].rx_buf = &req->scratch; req->xfer[1].len = 2; /* for 1uF, settle for 800 usec; no cap, 100 usec. */ req->xfer[1].delay_usecs = ts->vref_delay_usecs; spi_message_add_tail(&req->xfer[1], &req->msg); } /* take sample */ req->command = (u8) command; req->xfer[2].tx_buf = &req->command; req->xfer[2].len = 1; spi_message_add_tail(&req->xfer[2], &req->msg); req->xfer[3].rx_buf = &req->sample; req->xfer[3].len = 2; spi_message_add_tail(&req->xfer[3], &req->msg); /* REVISIT: take a few more samples, and compare ... */ /* converter in low power mode & enable PENIRQ */ req->ref_off = PWRDOWN; req->xfer[4].tx_buf = &req->ref_off; req->xfer[4].len = 1; spi_message_add_tail(&req->xfer[4], &req->msg); req->xfer[5].rx_buf = &req->scratch; req->xfer[5].len = 2; CS_CHANGE(req->xfer[5]); spi_message_add_tail(&req->xfer[5], &req->msg); ts->irq_disabled = 1; disable_irq(spi->irq); status = spi_sync(spi, &req->msg); ts->irq_disabled = 0; enable_irq(spi->irq); if (req->msg.status) status = req->msg.status; /* on-wire is a must-ignore bit, a BE12 value, then padding */ sample = be16_to_cpu(req->sample); sample = sample >> 3; sample &= 0x0fff; kfree(req); return status ? status : sample; }
/* * Erase pages of flash. */ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) { struct dataflash *priv = mtd->priv; struct spi_device *spi = priv->spi; struct spi_transfer x = { .tx_dma = 0, }; struct spi_message msg; unsigned blocksize = priv->page_size << 3; uint8_t *command; uint32_t rem; pr_debug("%s: erase addr=0x%llx len 0x%llx\n", dev_name(&spi->dev), (long long)instr->addr, (long long)instr->len); div_u64_rem(instr->len, priv->page_size, &rem); if (rem) return -EINVAL; div_u64_rem(instr->addr, priv->page_size, &rem); if (rem) return -EINVAL; spi_message_init(&msg); x.tx_buf = command = priv->command; x.len = 4; spi_message_add_tail(&x, &msg); mutex_lock(&priv->lock); while (instr->len > 0) { unsigned int pageaddr; int status; int do_block; /* Calculate flash page address; use block erase (for speed) if * we're at a block boundary and need to erase the whole block. */ pageaddr = div_u64(instr->addr, priv->page_size); do_block = (pageaddr & 0x7) == 0 && instr->len >= blocksize; pageaddr = pageaddr << priv->page_offset; command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE; command[1] = (uint8_t)(pageaddr >> 16); command[2] = (uint8_t)(pageaddr >> 8); command[3] = 0; pr_debug("ERASE %s: (%x) %x %x %x [%i]\n", do_block ? "block" : "page", command[0], command[1], command[2], command[3], pageaddr); status = spi_sync(spi, &msg); (void) dataflash_waitready(spi); if (status < 0) { printk(KERN_ERR "%s: erase %x, err %d\n", dev_name(&spi->dev), pageaddr, status); /* REVISIT: can retry instr->retries times; or * giveup and instr->fail_addr = instr->addr; */ continue; } if (do_block) { instr->addr += blocksize; instr->len -= blocksize; } else { instr->addr += priv->page_size; instr->len -= priv->page_size; } } mutex_unlock(&priv->lock); /* Inform MTD subsystem that erase is complete */ instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); return 0; } /* * Read from the DataFlash device. * from : Start offset in flash device * len : Amount to read * retlen : About of data actually read * buf : Buffer containing the data */ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct dataflash *priv = mtd->priv; struct spi_transfer x[2] = { { .tx_dma = 0, }, }; struct spi_message msg; unsigned int addr; uint8_t *command; int status; pr_debug("%s: read 0x%x..0x%x\n", dev_name(&priv->spi->dev), (unsigned)from, (unsigned)(from + len)); /* Calculate flash page/byte address */ addr = (((unsigned)from / priv->page_size) << priv->page_offset) + ((unsigned)from % priv->page_size); command = priv->command; pr_debug("READ: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); spi_message_init(&msg); x[0].tx_buf = command; x[0].len = 8; spi_message_add_tail(&x[0], &msg); x[1].rx_buf = buf; x[1].len = len; spi_message_add_tail(&x[1], &msg); mutex_lock(&priv->lock); /* Continuous read, max clock = f(car) which may be less than * the peak rate available. Some chips support commands with * fewer "don't care" bytes. Both buffers stay unchanged. */ command[0] = OP_READ_CONTINUOUS; command[1] = (uint8_t)(addr >> 16); command[2] = (uint8_t)(addr >> 8); command[3] = (uint8_t)(addr >> 0); /* plus 4 "don't care" bytes */ status = spi_sync(priv->spi, &msg); mutex_unlock(&priv->lock); if (status >= 0) { *retlen = msg.actual_length - 8; status = 0; } else pr_debug("%s: read %x..%x --> %d\n", dev_name(&priv->spi->dev), (unsigned)from, (unsigned)(from + len), status); return status; }
static int wm0010_stage2_load(struct snd_soc_codec *codec) { struct spi_device *spi = to_spi_device(codec->dev); struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); const struct firmware *fw; struct spi_message m; struct spi_transfer t; u32 *img; u8 *out; int i; int ret = 0; ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev); if (ret != 0) { dev_err(codec->dev, "Failed to request stage2 loader: %d\n", ret); return ret; } dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size); /* Copy to local buffer first as vmalloc causes problems for dma */ img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); if (!img) { ret = -ENOMEM; goto abort2; } out = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); if (!out) { ret = -ENOMEM; goto abort1; } memcpy(img, &fw->data[0], fw->size); spi_message_init(&m); memset(&t, 0, sizeof(t)); t.rx_buf = out; t.tx_buf = img; t.len = fw->size; t.bits_per_word = 8; t.speed_hz = wm0010->sysclk / 10; spi_message_add_tail(&t, &m); dev_dbg(codec->dev, "Starting initial download at %dHz\n", t.speed_hz); ret = spi_sync(spi, &m); if (ret != 0) { dev_err(codec->dev, "Initial download failed: %d\n", ret); goto abort; } /* Look for errors from the boot ROM */ for (i = 0; i < fw->size; i++) { if (out[i] != 0x55) { dev_err(codec->dev, "Boot ROM error: %x in %d\n", out[i], i); wm0010_mark_boot_failure(wm0010); ret = -EBUSY; goto abort; } } abort: kfree(out); abort1: kfree(img); abort2: release_firmware(fw); return ret; }
static int wm0010_boot(struct snd_soc_codec *codec) { struct spi_device *spi = to_spi_device(codec->dev); struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); unsigned long flags; int ret; struct spi_message m; struct spi_transfer t; struct dfw_pllrec pll_rec; u32 *p, len; u64 *img_swap; u8 *out; int i; spin_lock_irqsave(&wm0010->irq_lock, flags); if (wm0010->state != WM0010_POWER_OFF) dev_warn(wm0010->dev, "DSP already powered up!\n"); spin_unlock_irqrestore(&wm0010->irq_lock, flags); if (wm0010->sysclk > 26000000) { dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n"); ret = -ECANCELED; goto err; } mutex_lock(&wm0010->lock); wm0010->pll_running = false; dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq); ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies), wm0010->core_supplies); if (ret != 0) { dev_err(&spi->dev, "Failed to enable core supplies: %d\n", ret); mutex_unlock(&wm0010->lock); goto err; } ret = regulator_enable(wm0010->dbvdd); if (ret != 0) { dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret); goto err_core; } /* Release reset */ gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value); spin_lock_irqsave(&wm0010->irq_lock, flags); wm0010->state = WM0010_OUT_OF_RESET; spin_unlock_irqrestore(&wm0010->irq_lock, flags); if (!wait_for_completion_timeout(&wm0010->boot_completion, msecs_to_jiffies(20))) dev_err(codec->dev, "Failed to get interrupt from DSP\n"); spin_lock_irqsave(&wm0010->irq_lock, flags); wm0010->state = WM0010_BOOTROM; spin_unlock_irqrestore(&wm0010->irq_lock, flags); ret = wm0010_stage2_load(codec); if (ret) goto abort; if (!wait_for_completion_timeout(&wm0010->boot_completion, msecs_to_jiffies(20))) dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n"); spin_lock_irqsave(&wm0010->irq_lock, flags); wm0010->state = WM0010_STAGE2; spin_unlock_irqrestore(&wm0010->irq_lock, flags); /* Only initialise PLL if max_spi_freq initialised */ if (wm0010->max_spi_freq) { /* Initialise a PLL record */ memset(&pll_rec, 0, sizeof(pll_rec)); pll_rec.command = DFW_CMD_PLL; pll_rec.length = (sizeof(pll_rec) - 8); /* On wm0010 only the CLKCTRL1 value is used */ pll_rec.clkctrl1 = wm0010->pll_clkctrl1; ret = -ENOMEM; len = pll_rec.length + 8; out = kzalloc(len, GFP_KERNEL | GFP_DMA); if (!out) goto abort; img_swap = kzalloc(len, GFP_KERNEL | GFP_DMA); if (!img_swap) goto abort_out; /* We need to re-order for 0010 */ byte_swap_64((u64 *)&pll_rec, img_swap, len); spi_message_init(&m); memset(&t, 0, sizeof(t)); t.rx_buf = out; t.tx_buf = img_swap; t.len = len; t.bits_per_word = 8; t.speed_hz = wm0010->sysclk / 6; spi_message_add_tail(&t, &m); ret = spi_sync(spi, &m); if (ret) { dev_err(codec->dev, "First PLL write failed: %d\n", ret); goto abort_swap; } /* Use a second send of the message to get the return status */ ret = spi_sync(spi, &m); if (ret) { dev_err(codec->dev, "Second PLL write failed: %d\n", ret); goto abort_swap; } p = (u32 *)out; /* Look for PLL active code from the DSP */ for (i = 0; i < len / 4; i++) { if (*p == 0x0e00ed0f) { dev_dbg(codec->dev, "PLL packet received\n"); wm0010->pll_running = true; break; } p++; } kfree(img_swap); kfree(out); } else dev_dbg(codec->dev, "Not enabling DSP PLL."); ret = wm0010_firmware_load("wm0010.dfw", codec); if (ret != 0) goto abort; spin_lock_irqsave(&wm0010->irq_lock, flags); wm0010->state = WM0010_FIRMWARE; spin_unlock_irqrestore(&wm0010->irq_lock, flags); mutex_unlock(&wm0010->lock); return 0; abort_swap: kfree(img_swap); abort_out: kfree(out); abort: /* Put the chip back into reset */ wm0010_halt(codec); mutex_unlock(&wm0010->lock); return ret; err_core: mutex_unlock(&wm0010->lock); regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), wm0010->core_supplies); err: return ret; }
static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec) { struct spi_device *spi = to_spi_device(codec->dev); struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); struct list_head xfer_list; struct wm0010_boot_xfer *xfer; int ret; struct completion done; const struct firmware *fw; const struct dfw_binrec *rec; const struct dfw_inforec *inforec; u64 *img; u8 *out, dsp; u32 len, offset; INIT_LIST_HEAD(&xfer_list); ret = request_firmware(&fw, name, codec->dev); if (ret != 0) { dev_err(codec->dev, "Failed to request application(%s): %d\n", name, ret); return ret; } rec = (const struct dfw_binrec *)fw->data; inforec = (const struct dfw_inforec *)rec->data; offset = 0; dsp = inforec->dsp_target; wm0010->boot_failed = false; if (WARN_ON(!list_empty(&xfer_list))) return -EINVAL; init_completion(&done); /* First record should be INFO */ if (rec->command != DFW_CMD_INFO) { dev_err(codec->dev, "First record not INFO\r\n"); ret = -EINVAL; goto abort; } if (inforec->info_version != INFO_VERSION) { dev_err(codec->dev, "Unsupported version (%02d) of INFO record\r\n", inforec->info_version); ret = -EINVAL; goto abort; } dev_dbg(codec->dev, "Version v%02d INFO record found\r\n", inforec->info_version); /* Check it's a DSP file */ if (dsp != DEVICE_ID_WM0010) { dev_err(codec->dev, "Not a WM0010 firmware file.\r\n"); ret = -EINVAL; goto abort; } /* Skip the info record as we don't need to send it */ offset += ((rec->length) + 8); rec = (void *)&rec->data[rec->length]; while (offset < fw->size) { dev_dbg(codec->dev, "Packet: command %d, data length = 0x%x\r\n", rec->command, rec->length); len = rec->length + 8; xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); if (!xfer) { ret = -ENOMEM; goto abort; } xfer->codec = codec; list_add_tail(&xfer->list, &xfer_list); out = kzalloc(len, GFP_KERNEL | GFP_DMA); if (!out) { ret = -ENOMEM; goto abort1; } xfer->t.rx_buf = out; img = kzalloc(len, GFP_KERNEL | GFP_DMA); if (!img) { ret = -ENOMEM; goto abort1; } xfer->t.tx_buf = img; byte_swap_64((u64 *)&rec->command, img, len); spi_message_init(&xfer->m); xfer->m.complete = wm0010_boot_xfer_complete; xfer->m.context = xfer; xfer->t.len = len; xfer->t.bits_per_word = 8; if (!wm0010->pll_running) { xfer->t.speed_hz = wm0010->sysclk / 6; } else { xfer->t.speed_hz = wm0010->max_spi_freq; if (wm0010->board_max_spi_speed && (wm0010->board_max_spi_speed < wm0010->max_spi_freq)) xfer->t.speed_hz = wm0010->board_max_spi_speed; } /* Store max usable spi frequency for later use */ wm0010->max_spi_freq = xfer->t.speed_hz; spi_message_add_tail(&xfer->t, &xfer->m); offset += ((rec->length) + 8); rec = (void *)&rec->data[rec->length]; if (offset >= fw->size) { dev_dbg(codec->dev, "All transfers scheduled\n"); xfer->done = &done; } ret = spi_async(spi, &xfer->m); if (ret != 0) { dev_err(codec->dev, "Write failed: %d\n", ret); goto abort1; } if (wm0010->boot_failed) { dev_dbg(codec->dev, "Boot fail!\n"); ret = -EINVAL; goto abort1; } } wait_for_completion(&done); ret = 0; abort1: while (!list_empty(&xfer_list)) { xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer, list); kfree(xfer->t.rx_buf); kfree(xfer->t.tx_buf); list_del(&xfer->list); kfree(xfer); } abort: release_firmware(fw); return ret; }
/** * spi_mem_exec_op() - Execute a memory operation * @mem: the SPI memory * @op: the memory operation to execute * * Executes a memory operation. * * This function first checks that @op is supported and then tries to execute * it. * * Return: 0 in case of success, a negative error code otherwise. */ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) { unsigned int tmpbufsize, xferpos = 0, totalxferlen = 0; struct spi_controller *ctlr = mem->spi->controller; struct spi_transfer xfers[4] = { }; struct spi_message msg; u8 *tmpbuf; int ret; ret = spi_mem_check_op(op); if (ret) return ret; if (!spi_mem_internal_supports_op(mem, op)) return -ENOTSUPP; if (ctlr->mem_ops) { ret = spi_mem_access_start(mem); if (ret) return ret; ret = ctlr->mem_ops->exec_op(mem, op); spi_mem_access_end(mem); /* * Some controllers only optimize specific paths (typically the * read path) and expect the core to use the regular SPI * interface in other cases. */ if (!ret || ret != -ENOTSUPP) return ret; } tmpbufsize = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes; /* * Allocate a buffer to transmit the CMD, ADDR cycles with kmalloc() so * we're guaranteed that this buffer is DMA-able, as required by the * SPI layer. */ tmpbuf = kzalloc(tmpbufsize, GFP_KERNEL); if (!tmpbuf) return -ENOMEM; spi_message_init(&msg); tmpbuf[0] = op->cmd.opcode; xfers[xferpos].tx_buf = tmpbuf; xfers[xferpos].len = sizeof(op->cmd.opcode); spi_message_add_tail(&xfers[xferpos], &msg); xferpos++; totalxferlen++; if (op->addr.nbytes) { int i; for (i = 0; i < op->addr.nbytes; i++) tmpbuf[i + 1] = op->addr.val >> (8 * (op->addr.nbytes - i - 1)); xfers[xferpos].tx_buf = tmpbuf + 1; xfers[xferpos].len = op->addr.nbytes; spi_message_add_tail(&xfers[xferpos], &msg); xferpos++; totalxferlen += op->addr.nbytes; }
int ade7758_configure_ring(struct iio_dev *indio_dev) { struct ade7758_state *st = iio_priv(indio_dev); int ret = 0; indio_dev->buffer = iio_kfifo_allocate(indio_dev); if (!indio_dev->buffer) { ret = -ENOMEM; return ret; } indio_dev->setup_ops = &ade7758_ring_setup_ops; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &ade7758_trigger_handler, 0, indio_dev, "ade7759_consumer%d", indio_dev->id); if (indio_dev->pollfunc == NULL) { ret = -ENOMEM; goto error_iio_kfifo_free; } indio_dev->modes |= INDIO_BUFFER_TRIGGERED; st->tx_buf[0] = ADE7758_READ_REG(ADE7758_RSTATUS); st->tx_buf[1] = 0; st->tx_buf[2] = 0; st->tx_buf[3] = 0; st->tx_buf[4] = ADE7758_READ_REG(ADE7758_WFORM); st->tx_buf[5] = 0; st->tx_buf[6] = 0; st->tx_buf[7] = 0; /* build spi ring message */ st->ring_xfer[0].tx_buf = &st->tx_buf[0]; st->ring_xfer[0].len = 1; st->ring_xfer[0].bits_per_word = 8; st->ring_xfer[0].delay_usecs = 4; st->ring_xfer[1].rx_buf = &st->rx_buf[1]; st->ring_xfer[1].len = 3; st->ring_xfer[1].bits_per_word = 8; st->ring_xfer[1].cs_change = 1; st->ring_xfer[2].tx_buf = &st->tx_buf[4]; st->ring_xfer[2].len = 1; st->ring_xfer[2].bits_per_word = 8; st->ring_xfer[2].delay_usecs = 1; st->ring_xfer[3].rx_buf = &st->rx_buf[5]; st->ring_xfer[3].len = 3; st->ring_xfer[3].bits_per_word = 8; spi_message_init(&st->ring_msg); spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg); spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg); spi_message_add_tail(&st->ring_xfer[2], &st->ring_msg); spi_message_add_tail(&st->ring_xfer[3], &st->ring_msg); return 0; error_iio_kfifo_free: iio_kfifo_free(indio_dev->buffer); return ret; }
/* * Erase an address range on the flash chip. The address range may extend * one or more erase sectors. Return an error is there is a problem erasing. */ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) { struct m25p *flash = mtd_to_m25p(mtd); u32 addr,len; uint64_t tmpdiv; int rem, rem1; DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n", flash->spi->dev.bus_id, __FUNCTION__, "at", (u32)instr->addr, instr->len); /* sanity checks */ if (instr->addr + instr->len > device_size(&(flash->mtd))) return -EINVAL; tmpdiv = (uint64_t) instr->addr; rem = do_div(tmpdiv, mtd->erasesize); tmpdiv = (uint64_t) instr->len; rem1 = do_div(tmpdiv, mtd->erasesize); if (rem != 0 || rem1 != 0) { return -EINVAL; } addr = instr->addr; len = instr->len; mutex_lock(&flash->lock); /* REVISIT in some cases we could speed up erasing large regions * by using OPCODE_SE instead of OPCODE_BE_4K */ /* now erase those sectors */ while (len) { #ifdef CONFIG_MIPS_BRCM97XXX /* BSPI remaps each 4MB segment */ if (erase_sector(flash, (addr + 0x400000) & 0xffffff)) { #else if (erase_sector(flash, addr)) { #endif instr->state = MTD_ERASE_FAILED; mutex_unlock(&flash->lock); return -EIO; } addr += mtd->erasesize; len -= mtd->erasesize; } mutex_unlock(&flash->lock); instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); return 0; } /* * Read an address range from the flash chip. The address range * may be any size provided it is within the physical boundaries. */ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct m25p *flash = mtd_to_m25p(mtd); struct spi_transfer t[2]; struct spi_message m; size_t total_len = len; DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", flash->spi->dev.bus_id, __FUNCTION__, "from", (u32)from, len); /* sanity checks */ if (!len) return 0; if (from + len > device_size(&(flash->mtd))) return -EINVAL; if (retlen) *retlen = 0; total_len = len; while(total_len) { len = total_len; #if 0 //defined(BRCM_SPI_SS_WAR) /* * For testing purposes only - read 12 bytes at a time: * * 3548a0 MSPI has a 12-byte limit (PR42350). * MSPI emulated via BSPI has no such limit. * In production BSPI is always used because it is much faster. */ if(len > 12) len = 12; #endif #ifdef CONFIG_MIPS_BRCM97XXX /* don't cross a 4MB boundary due to remapping */ len = min(len, (0x400000 - ((u32)from & 0x3fffff))); #endif spi_message_init(&m); memset(t, 0, (sizeof t)); t[0].tx_buf = flash->command; t[0].len = sizeof(flash->command); spi_message_add_tail(&t[0], &m); t[1].rx_buf = buf; t[1].len = len; spi_message_add_tail(&t[1], &m); /* Byte count starts at zero. */ mutex_lock(&flash->lock); /* Wait till previous write/erase is done. */ if (wait_till_ready(flash)) { /* REVISIT status return?? */ mutex_unlock(&flash->lock); return 1; } /* FIXME switch to OPCODE_FAST_READ. It's required for higher * clocks; and at this writing, every chip this driver handles * supports that opcode. */ /* Set up the write data buffer. */ flash->command[0] = OPCODE_READ; #ifdef CONFIG_MIPS_BRCM97XXX /* BSPI remaps each 4MB segment */ flash->command[1] = ((from >> 16) + 0x40) & 0xff; #else flash->command[1] = from >> 16; #endif flash->command[2] = from >> 8; flash->command[3] = from; spi_sync(flash->spi, &m); *retlen += m.actual_length - sizeof(flash->command); mutex_unlock(&flash->lock); from += len; buf += len; total_len -= len; } return 0; } /* * Write an address range to the flash chip. Data must be written in * FLASH_PAGESIZE chunks. The address range may be any size provided * it is within the physical boundaries. */ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct m25p *flash = mtd_to_m25p(mtd); u32 page_offset, page_size; struct spi_transfer t[2]; struct spi_message m; DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", flash->spi->dev.bus_id, __FUNCTION__, "to", (u32)to, len); if (retlen) *retlen = 0; /* sanity checks */ if (!len) return(0); if (to + len > device_size(&(flash->mtd))) return -EINVAL; #ifdef BRCM_SPI_SS_WAR if(len > 12) return -EIO; #endif spi_message_init(&m); memset(t, 0, (sizeof t)); t[0].tx_buf = flash->command; t[0].len = sizeof(flash->command); spi_message_add_tail(&t[0], &m); t[1].tx_buf = buf; spi_message_add_tail(&t[1], &m); mutex_lock(&flash->lock); /* Wait until finished previous write command. */ if (wait_till_ready(flash)) return 1; write_enable(flash); /* Set up the opcode in the write buffer. */ flash->command[0] = OPCODE_PP; #ifdef CONFIG_MIPS_BRCM97XXX /* BSPI remaps each 4MB segment */ flash->command[1] = ((to >> 16) + 0x40) & 0xff; #else flash->command[1] = to >> 16; #endif flash->command[2] = to >> 8; flash->command[3] = to; /* what page do we start with? */ page_offset = to % FLASH_PAGESIZE; /* do all the bytes fit onto one page? */ if (page_offset + len <= FLASH_PAGESIZE) { t[1].len = len; spi_sync(flash->spi, &m); *retlen = m.actual_length - sizeof(flash->command); } else { u32 i; /* the size of data remaining on the first page */ page_size = FLASH_PAGESIZE - page_offset; t[1].len = page_size; spi_sync(flash->spi, &m); *retlen = m.actual_length - sizeof(flash->command); /* write everything in PAGESIZE chunks */ for (i = page_size; i < len; i += page_size) { page_size = len - i; if (page_size > FLASH_PAGESIZE) page_size = FLASH_PAGESIZE; /* write the next page to flash */ #ifdef CONFIG_MIPS_BRCM97XXX /* BSPI remaps each 4MB segment */ flash->command[1] = (((to + i) >> 16) + 0x40) & 0xff; #else flash->command[1] = (to + i) >> 16; #endif flash->command[2] = (to + i) >> 8; flash->command[3] = (to + i); t[1].tx_buf = buf + i; t[1].len = page_size; wait_till_ready(flash); write_enable(flash); spi_sync(flash->spi, &m); if (retlen) *retlen += m.actual_length - sizeof(flash->command); } } mutex_unlock(&flash->lock); return 0; } /****************************************************************************/ /* * SPI device driver setup and teardown */ struct flash_info { char *name; /* JEDEC id zero means "no ID" (most older chips); otherwise it has * a high byte of zero plus three data bytes: the manufacturer id, * then a two byte device id. */ u32 jedec_id; /* The size listed here is what works with OPCODE_SE, which isn't * necessarily called a "sector" by the vendor. */ unsigned sector_size; u16 n_sectors; u16 flags; #define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ }; /* NOTE: double check command sets and memory organization when you add * more flash chips. This current list focusses on newer chips, which * have been converging on command sets which including JEDEC ID. */ static struct flash_info __devinitdata m25p_data [] = { /* Atmel -- some are (confusingly) marketed as "DataFlash" */ { "at25fs010", 0x1f6601, 32 * 1024, 4, SECT_4K, }, { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, }, { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, }, { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, }, { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, }, { "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, }, { "at26df321", 0x1f4701, 64 * 1024, 64, SECT_4K, }, /* Spansion -- single (large) sector size only, at least * for the chips listed here (without boot sectors). */ { "s25sl004a", 0x010212, 64 * 1024, 8, }, { "s25sl008a", 0x010213, 64 * 1024, 16, }, { "s25sl016a", 0x010214, 64 * 1024, 32, }, { "s25sl032a", 0x010215, 64 * 1024, 64, }, { "s25sl064a", 0x010216, 64 * 1024, 128, }, #ifdef CONFIG_MIPS_BRCM97XXX { "s25fl128p", 0x012018, 64 * 1024, 256, }, #endif /* SST -- large erase sizes are "overlays", "sectors" are 4K */ { "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, }, { "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, }, { "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, }, { "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, }, /* ST Microelectronics -- newer production may have feature updates */ { "m25p05", 0x202010, 32 * 1024, 2, }, { "m25p10", 0x202011, 32 * 1024, 4, }, { "m25p20", 0x202012, 64 * 1024, 4, }, { "m25p40", 0x202013, 64 * 1024, 8, }, #ifndef CONFIG_MIPS_BRCM97XXX /* ID 0 is detected when there's nothing on the bus */ { "m25p80", 0, 64 * 1024, 16, }, #endif { "m25p16", 0x202015, 64 * 1024, 32, }, { "m25p32", 0x202016, 64 * 1024, 64, }, { "m25p64", 0x202017, 64 * 1024, 128, }, { "m25p128", 0x202018, 256 * 1024, 64, }, { "m45pe80", 0x204014, 64 * 1024, 16, }, { "m45pe16", 0x204015, 64 * 1024, 32, }, { "m25pe80", 0x208014, 64 * 1024, 16, }, { "m25pe16", 0x208015, 64 * 1024, 32, SECT_4K, }, /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ { "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, }, { "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, }, { "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, }, { "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, }, { "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, }, { "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, }, { "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, }, }; static struct flash_info *__devinit jedec_probe(struct spi_device *spi) { int tmp; u8 code = OPCODE_RDID; u8 id[3]; u32 jedec; struct flash_info *info; /* JEDEC also defines an optional "extended device information" * string for after vendor-specific data, after the three bytes * we use here. Supporting some chips might require using it. */ tmp = spi_write_then_read(spi, &code, 1, id, 3); if (tmp < 0) { DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n", spi->dev.bus_id, tmp); return NULL; } jedec = id[0]; jedec = jedec << 8; jedec |= id[1]; jedec = jedec << 8; jedec |= id[2]; for (tmp = 0, info = m25p_data; tmp < ARRAY_SIZE(m25p_data); tmp++, info++) { if (info->jedec_id == jedec) return info; } dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec); return NULL; }
/* * Write to the DataFlash device. * to : Start offset in flash device * len : Amount to write * retlen : Amount of data actually written * buf : Buffer containing the data */ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf) { struct dataflash *priv = mtd->priv; struct spi_device *spi = priv->spi; struct spi_transfer x[2]; struct spi_message msg; unsigned int pageaddr, addr, offset, writelen; size_t remaining = len; u_char *writebuf = (u_char *) buf; int status = -EINVAL; uint8_t *command; pr_debug("%s: write 0x%x..0x%x\n", dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len)); spi_message_init(&msg); memset(&x[0], 0, sizeof(struct spi_transfer) * 2); x[0].tx_buf = command = priv->command; x[0].len = 4; spi_message_add_tail(&x[0], &msg); pageaddr = ((unsigned)to / priv->page_size); offset = ((unsigned)to % priv->page_size); if (offset + len > priv->page_size) writelen = priv->page_size - offset; else writelen = len; while (remaining > 0) { pr_debug("write @ %i:%i len=%i\n", pageaddr, offset, writelen); /* REVISIT: * (a) each page in a sector must be rewritten at least * once every 10K sibling erase/program operations. * (b) for pages that are already erased, we could * use WRITE+MWRITE not PROGRAM for ~30% speedup. * (c) WRITE to buffer could be done while waiting for * a previous MWRITE/MWERASE to complete ... * (d) error handling here seems to be mostly missing. * * Two persistent bits per page, plus a per-sector counter, * could support (a) and (b) ... we might consider using * the second half of sector zero, which is just one block, * to track that state. (On AT91, that sector should also * support boot-from-DataFlash.) */ addr = pageaddr << priv->page_offset; /* (1) Maybe transfer partial page to Buffer1 */ if (writelen != priv->page_size) { command[0] = OP_TRANSFER_BUF1; command[1] = (addr & 0x00FF0000) >> 16; command[2] = (addr & 0x0000FF00) >> 8; command[3] = 0; pr_debug("TRANSFER: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); status = spi_sync(spi, &msg); if (status < 0) pr_debug("%s: xfer %u -> %d\n", dev_name(&spi->dev), addr, status); (void) dataflash_waitready(priv->spi); } /* (2) Program full page via Buffer1 */ addr += offset; command[0] = OP_PROGRAM_VIA_BUF1; command[1] = (addr & 0x00FF0000) >> 16; command[2] = (addr & 0x0000FF00) >> 8; command[3] = (addr & 0x000000FF); pr_debug("PROGRAM: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); x[1].tx_buf = writebuf; x[1].len = writelen; spi_message_add_tail(x + 1, &msg); status = spi_sync(spi, &msg); spi_transfer_del(x + 1); if (status < 0) pr_debug("%s: pgm %u/%u -> %d\n", dev_name(&spi->dev), addr, writelen, status); (void) dataflash_waitready(priv->spi); #ifdef CONFIG_MTD_DATAFLASH_WRITE_VERIFY /* (3) Compare to Buffer1 */ addr = pageaddr << priv->page_offset; command[0] = OP_COMPARE_BUF1; command[1] = (addr & 0x00FF0000) >> 16; command[2] = (addr & 0x0000FF00) >> 8; command[3] = 0; pr_debug("COMPARE: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); status = spi_sync(spi, &msg); if (status < 0) pr_debug("%s: compare %u -> %d\n", dev_name(&spi->dev), addr, status); status = dataflash_waitready(priv->spi); /* Check result of the compare operation */ if (status & (1 << 6)) { printk(KERN_ERR "%s: compare page %u, err %d\n", dev_name(&spi->dev), pageaddr, status); remaining = 0; status = -EIO; break; } else status = 0; #endif /* CONFIG_MTD_DATAFLASH_WRITE_VERIFY */ remaining = remaining - writelen; pageaddr++; offset = 0; writebuf += writelen; *retlen += writelen; if (remaining > priv->page_size) writelen = priv->page_size; else writelen = remaining; }