Lines Matching refs:cfi
1 /* Common Flash Memory Interface (CFI) model.
40 #include "dv-cfi.h"
57 /* This is the structure that all CFI conforming devices must provided
62 CFI spec and review that (see top of this file for URIs). */
124 it is dynamic, we'll provide that from "struct cfi" when requested. */
138 struct cfi;
148 void (*setup) (struct hw *me, struct cfi *cfi);
149 bool (*write) (struct hw *me, struct cfi *cfi, const void *source,
151 bool (*read) (struct hw *me, struct cfi *cfi, void *dest,
158 struct cfi
179 /* Erase the block specified by the offset into the given CFI flash. */
181 cfi_erase_block (struct hw *me, struct cfi *cfi, unsigned offset)
188 if (!cfi->query.num_erase_regions)
189 memset (cfi->data, 0xff, cfi->dev_size);
191 for (i = 0; i < cfi->query.num_erase_regions; ++i)
193 region = &cfi->erase_regions[i];
201 memset (cfi->data + offset, 0xff, region->size);
210 cfi_unshift_addr (struct cfi *cfi, unsigned addr)
212 switch (cfi->width)
220 /* CFI requires all values to be little endian in its structure, so
233 cmdset_intel_write (struct hw *me, struct cfi *cfi, const void *source,
236 switch (cfi->state)
243 cfi->state = CFI_STATE_ERASE;
247 cfi->state = CFI_STATE_WRITE;
250 cfi->status = INTEL_SR_DWS;
253 cfi->state = CFI_STATE_PROTECT;
263 cfi_erase_block (me, cfi, offset);
264 cfi->status &= ~(INTEL_SR_PS | INTEL_SR_ES);
267 cfi->status |= INTEL_SR_PS | INTEL_SR_ES;
268 cfi->state = CFI_STATE_STATUS;
281 cfi->status |= INTEL_SR_PS | INTEL_SR_ES;
284 cfi->state = CFI_STATE_STATUS;
295 cmdset_intel_read (struct hw *me, struct cfi *cfi, void *dest,
300 switch (cfi->state)
304 *sdest = cfi->status;
337 cmdset_intel_setup (struct hw *me, struct cfi *cfi)
339 cfi->status = INTEL_SR_DWS;
364 struct cfi *cfi = hw_data (me);
369 offset = addr & (cfi->dev_size - 1);
370 shifted_offset = cfi_unshift_addr (cfi, offset);
372 if (cfi->width != nr_bytes)
375 (unsigned long) addr, nr_bytes, cfi->width));
379 if (cfi->state == CFI_STATE_WRITE)
387 cfi->data[offset + i] &= ssource[i];
389 cfi->state = CFI_STATE_STATUS;
396 old_state = cfi->state;
400 cfi->state = CFI_STATE_READ;
404 switch (cfi->state)
411 cfi->state = CFI_STATE_CFI_QUERY;
417 cfi->state = CFI_STATE_READ_ID;
424 if (!cfi->cmdset->write (me, cfi, source, offset, value, nr_bytes))
435 state_names[old_state], state_names[cfi->state]));
442 flash, the CFI query structure, some status info, or something else ?
449 struct cfi *cfi = hw_data (me);
453 offset = addr & (cfi->dev_size - 1);
454 shifted_offset = cfi_unshift_addr (cfi, offset);
458 if (cfi->state != CFI_STATE_READ && cfi->width != nr_bytes)
461 (unsigned long) addr, nr_bytes, cfi->width));
467 state_names[cfi->state], (unsigned long) addr, nr_bytes));
469 switch (cfi->state)
472 memcpy (dest, cfi->data + offset, nr_bytes);
477 shifted_offset < CFI_ADDR_CFI_QUERY_RESULT + sizeof (cfi->query) +
478 (cfi->query.num_erase_regions * 4))
483 if (shifted_offset >= sizeof (cfi->query))
485 qry = cfi->erase_region_info;
486 shifted_offset -= sizeof (cfi->query);
489 qry = (void *) &cfi->query;
500 if (!cfi->cmdset->read (me, cfi, dest, offset, shifted_offset, nr_bytes))
501 HW_TRACE ((me, "unhandled state %s", state_names[cfi->state]));
514 struct cfi *cfi = hw_data (me);
516 if (cfi->mmap)
517 munmap (cfi->mmap, cfi->dev_size);
521 /* Helper function to easily add CFI erase regions to the existing set. */
523 cfi_add_erase_region (struct hw *me, struct cfi *cfi,
526 unsigned num_regions = cfi->query.num_erase_regions;
531 region = &cfi->erase_regions[num_regions];
541 qry_region = cfi->erase_region_info + 4 * num_regions;
554 cfi->query.num_erase_regions = num_regions + 1;
584 attach_cfi_regs (struct hw *me, struct cfi *cfi)
614 cfi_encode_16bit (cfi->query.p_id, ival);
618 cfi->cmdset = cfi_cmdsets[i];
619 if (cfi->cmdset == NULL)
625 cfi_encode_16bit (cfi->query.a_id, ival);
630 cfi->dev_size = hw_find_integer_property (me, "size");
632 cfi->dev_size = attach_size;
633 cfi->query.dev_size = log2 (cfi->dev_size);
638 cfi->width = hw_find_integer_property (me, "width");
639 if (cfi->width != 8 && cfi->width != 16 && cfi->width != 32)
640 hw_abort (me, "\"width\" must be 8 or 16 or 32, not %u", cfi->width);
644 cfi->width = 8;
646 cfi->width /= 8;
652 cfi_encode_16bit (cfi->query.max_buf_write_len, log2 (ival));
662 cfi->erase_region_info = HW_NALLOC (me, unsigned char, ret / 2);
663 cfi->erase_regions = HW_NALLOC (me, struct cfi_erase_region, ret / 2);
675 cfi_add_erase_region (me, cfi, blocks, size);
682 unsigned num = ARRAY_SIZE (cfi->query.voltages);
691 cfi->query.voltages[i] = ival;
698 unsigned num = ARRAY_SIZE (cfi->query.timeouts);
707 cfi->query.timeouts[i] = ival;
738 posix_fallocate (fd, 0, cfi->dev_size);
740 cfi->mmap = mmap (NULL, cfi->dev_size,
744 if (cfi->mmap == MAP_FAILED)
745 cfi->mmap = NULL;
747 cfi->data = cfi->mmap;
750 "cfi: sorry, file write support requires mmap()\n");
753 if (!cfi->data)
757 cfi->data = HW_NALLOC (me, unsigned char, cfi->dev_size);
765 read_len = fread (cfi->data, 1, cfi->dev_size, fp);
774 memset (cfi->data, 0xff, cfi->dev_size - read_len);
786 struct cfi *cfi;
788 cfi = HW_ZALLOC (me, struct cfi);
790 set_hw_data (me, cfi);
795 attach_cfi_regs (me, cfi);
797 /* Initialize the CFI. */
798 cfi->state = CFI_STATE_READ;
799 memcpy (cfi->query.qry, "QRY", 3);
800 cfi->cmdset->setup (me, cfi);
806 {"cfi", cfi_finish,},