Allow the sector size of the disk device to be configured using hints or

FDT data.  The sector size must be a multiple of the device's page size.
If not configured, use the historical default of the device page size.

Setting the disk sector size to 512 or 4096 allows a variety of standard
filesystems to be used on the device.  Of course you wouldn't want to be
writing frequently to a SPI flash chip like it was a disk drive, but for
data that gets written once (or rarely) and read often, using a standard
filesystem is a nice convenient thing.
This commit is contained in:
Ian Lepore 2019-03-02 23:20:47 +00:00
parent 2274a2f725
commit e70ece1297
2 changed files with 43 additions and 7 deletions

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 26, 2019
.Dd March 2, 2019
.Dt AT45D 4
.Os
.Sh NAME
@ -126,6 +126,10 @@ The following properties are optional for the
.Nm
device subnode:
.Bl -tag -width indent
.It Va freebsd,sectorsize
The sector size of the disk created for this storage device.
It must be a multiple of the device's page size.
The default is the device page size.
.It Va spi-cpha
Empty property indicating the slave device requires shifted clock
phase (CPHA) mode.
@ -156,6 +160,10 @@ The chip-select number to assert when performing I/O for this device.
Set the high bit (1 << 31) to invert the logic level of the chip select line.
.It Va hint.at45d.%d.mode
The SPI mode (0-3) to use when communicating with this device.
.It Va hint.at45d.%d.sectorsize
The sector size of the disk created for this storage device.
It must be a multiple of the device's page size.
The default is the device page size.
.El
.Sh FILES
.Bl -tag -width /dev/flash/at45d?

View File

@ -288,9 +288,11 @@ at45d_detach(device_t dev)
AT45D_UNLOCK(sc);
if (err == 0 && sc->taskstate == TSTATE_STOPPED) {
disk_destroy(sc->disk);
bioq_flush(&sc->bio_queue, NULL, ENXIO);
free(sc->dummybuf, M_DEVBUF);
if (sc->disk) {
disk_destroy(sc->disk);
bioq_flush(&sc->bio_queue, NULL, ENXIO);
free(sc->dummybuf, M_DEVBUF);
}
AT45D_LOCK_DESTROY(sc);
}
return (err);
@ -303,6 +305,7 @@ at45d_delayed_attach(void *xsc)
struct at45d_mfg_info mfginfo;
const struct at45d_flash_ident *ident;
u_int i;
int sectorsize;
uint32_t jedec;
uint16_t pagesize;
uint8_t status;
@ -340,6 +343,30 @@ at45d_delayed_attach(void *xsc)
pagesize = ident->pagesize;
sc->pagesize = pagesize;
/*
* By default we set up a disk with a sector size that matches the
* device page size. If there is a device hint or fdt property
* requesting a different size, use that, as long as it is a multiple of
* the device page size).
*/
sectorsize = pagesize;
#ifdef FDT
{
pcell_t size;
if (OF_getencprop(ofw_bus_get_node(sc->dev),
"freebsd,sectorsize", &size, sizeof(size)) > 0)
sectorsize = size;
}
#endif
resource_int_value(device_get_name(sc->dev), device_get_unit(sc->dev),
"sectorsize", &sectorsize);
if ((sectorsize % pagesize) != 0) {
device_printf(sc->dev, "Invalid sectorsize %d, "
"must be a multiple of %d\n", sectorsize, pagesize);
return;
}
sc->dummybuf = malloc(pagesize, M_DEVBUF, M_WAITOK | M_ZERO);
sc->disk = disk_alloc();
@ -350,7 +377,7 @@ at45d_delayed_attach(void *xsc)
sc->disk->d_name = "flash/at45d";
sc->disk->d_drv1 = sc;
sc->disk->d_maxsize = DFLTPHYS;
sc->disk->d_sectorsize = pagesize;
sc->disk->d_sectorsize = sectorsize;
sc->disk->d_mediasize = pagesize * ident->pagecount;
sc->disk->d_unit = device_get_unit(sc->dev);
disk_create(sc->disk, DISK_VERSION);
@ -358,9 +385,10 @@ at45d_delayed_attach(void *xsc)
bioq_init(&sc->bio_queue);
kproc_create(&at45d_task, sc, &sc->p, 0, 0, "task: at45d flash");
sc->taskstate = TSTATE_RUNNING;
device_printf(sc->dev, "%s, %d bytes per page, %d pages; %d KBytes\n",
device_printf(sc->dev,
"%s, %d bytes per page, %d pages; %d KBytes; disk sector size %d\n",
ident->name, pagesize, ident->pagecount,
(pagesize * ident->pagecount) / 1024);
(pagesize * ident->pagecount) / 1024, sectorsize);
}
static int