2009-05-18 23:20:56 +00:00
|
|
|
/*-
|
2017-11-27 14:52:40 +00:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
|
|
|
*
|
2009-05-18 23:20:56 +00:00
|
|
|
* Copyright (c) 2009 Oleksandr Tymoshenko. All rights reserved.
|
2018-03-18 18:58:47 +00:00
|
|
|
* Copyright (c) 2018 Ian Lepore. All rights reserved.
|
2019-12-04 16:56:11 +00:00
|
|
|
* Copyright (c) 2006 M. Warner Losh <imp@FreeBSD.org>
|
2009-05-18 23:20:56 +00:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
2016-03-30 17:00:33 +00:00
|
|
|
#include "opt_platform.h"
|
|
|
|
|
2009-05-18 23:20:56 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/bio.h>
|
|
|
|
#include <sys/bus.h>
|
|
|
|
#include <sys/conf.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/kthread.h>
|
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/module.h>
|
|
|
|
#include <sys/mutex.h>
|
|
|
|
#include <geom/geom_disk.h>
|
|
|
|
|
2016-03-30 17:00:33 +00:00
|
|
|
#ifdef FDT
|
|
|
|
#include <dev/fdt/fdt_common.h>
|
|
|
|
#include <dev/ofw/ofw_bus_subr.h>
|
|
|
|
#include <dev/ofw/openfirm.h>
|
|
|
|
#endif
|
|
|
|
|
2009-05-18 23:20:56 +00:00
|
|
|
#include <dev/spibus/spi.h>
|
|
|
|
#include "spibus_if.h"
|
|
|
|
|
|
|
|
#include <dev/flash/mx25lreg.h>
|
|
|
|
|
2010-07-19 21:38:15 +00:00
|
|
|
#define FL_NONE 0x00
|
|
|
|
#define FL_ERASE_4K 0x01
|
|
|
|
#define FL_ERASE_32K 0x02
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
#define FL_ENABLE_4B_ADDR 0x04
|
|
|
|
#define FL_DISABLE_4B_ADDR 0x08
|
2010-07-19 21:38:15 +00:00
|
|
|
|
2011-02-16 20:07:44 +00:00
|
|
|
/*
|
|
|
|
* Define the sectorsize to be a smaller size rather than the flash
|
|
|
|
* sector size. Trying to run FFS off of a 64k flash sector size
|
|
|
|
* results in a completely un-usable system.
|
|
|
|
*/
|
|
|
|
#define MX25L_SECTORSIZE 512
|
|
|
|
|
2009-05-18 23:20:56 +00:00
|
|
|
struct mx25l_flash_ident
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
uint8_t manufacturer_id;
|
|
|
|
uint16_t device_id;
|
|
|
|
unsigned int sectorsize;
|
|
|
|
unsigned int sectorcount;
|
2010-07-19 21:38:15 +00:00
|
|
|
unsigned int flags;
|
2009-05-18 23:20:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct mx25l_softc
|
|
|
|
{
|
|
|
|
device_t sc_dev;
|
2018-03-18 17:25:23 +00:00
|
|
|
device_t sc_parent;
|
2009-05-18 23:20:56 +00:00
|
|
|
uint8_t sc_manufacturer_id;
|
|
|
|
uint16_t sc_device_id;
|
2018-03-18 18:37:47 +00:00
|
|
|
unsigned int sc_erasesize;
|
2009-05-18 23:20:56 +00:00
|
|
|
struct mtx sc_mtx;
|
|
|
|
struct disk *sc_disk;
|
|
|
|
struct proc *sc_p;
|
|
|
|
struct bio_queue_head sc_bio_queue;
|
2010-07-19 21:50:43 +00:00
|
|
|
unsigned int sc_flags;
|
2018-02-24 16:28:45 +00:00
|
|
|
unsigned int sc_taskstate;
|
2018-03-18 15:56:10 +00:00
|
|
|
uint8_t sc_dummybuf[FLASH_PAGE_SIZE];
|
2009-05-18 23:20:56 +00:00
|
|
|
};
|
|
|
|
|
2018-02-24 16:28:45 +00:00
|
|
|
#define TSTATE_STOPPED 0
|
|
|
|
#define TSTATE_STOPPING 1
|
|
|
|
#define TSTATE_RUNNING 2
|
|
|
|
|
2009-05-18 23:20:56 +00:00
|
|
|
#define M25PXX_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
|
|
|
|
#define M25PXX_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
|
|
|
|
#define M25PXX_LOCK_INIT(_sc) \
|
|
|
|
mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
|
|
|
|
"mx25l", MTX_DEF)
|
|
|
|
#define M25PXX_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
|
|
|
|
#define M25PXX_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
|
|
|
|
#define M25PXX_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
|
|
|
|
|
|
|
|
/* disk routines */
|
|
|
|
static int mx25l_open(struct disk *dp);
|
|
|
|
static int mx25l_close(struct disk *dp);
|
|
|
|
static int mx25l_ioctl(struct disk *, u_long, void *, int, struct thread *);
|
|
|
|
static void mx25l_strategy(struct bio *bp);
|
2016-01-22 03:15:53 +00:00
|
|
|
static int mx25l_getattr(struct bio *bp);
|
2009-05-18 23:20:56 +00:00
|
|
|
static void mx25l_task(void *arg);
|
|
|
|
|
2018-07-29 16:55:28 +00:00
|
|
|
static struct mx25l_flash_ident flash_devices[] = {
|
2012-09-25 22:12:07 +00:00
|
|
|
{ "en25f32", 0x1c, 0x3116, 64 * 1024, 64, FL_NONE },
|
|
|
|
{ "en25p32", 0x1c, 0x2016, 64 * 1024, 64, FL_NONE },
|
|
|
|
{ "en25p64", 0x1c, 0x2017, 64 * 1024, 128, FL_NONE },
|
2017-05-06 06:08:44 +00:00
|
|
|
{ "en25q32", 0x1c, 0x3016, 64 * 1024, 64, FL_NONE },
|
2012-09-25 22:12:07 +00:00
|
|
|
{ "en25q64", 0x1c, 0x3017, 64 * 1024, 128, FL_ERASE_4K },
|
2017-05-06 06:08:44 +00:00
|
|
|
{ "m25p32", 0x20, 0x2016, 64 * 1024, 64, FL_NONE },
|
2012-09-25 22:12:07 +00:00
|
|
|
{ "m25p64", 0x20, 0x2017, 64 * 1024, 128, FL_NONE },
|
2018-05-17 10:13:18 +00:00
|
|
|
{ "mx25l1606e", 0xc2, 0x2015, 64 * 1024, 32, FL_ERASE_4K},
|
2012-09-25 22:12:07 +00:00
|
|
|
{ "mx25ll32", 0xc2, 0x2016, 64 * 1024, 64, FL_NONE },
|
|
|
|
{ "mx25ll64", 0xc2, 0x2017, 64 * 1024, 128, FL_NONE },
|
|
|
|
{ "mx25ll128", 0xc2, 0x2018, 64 * 1024, 256, FL_ERASE_4K | FL_ERASE_32K },
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
{ "mx25ll256", 0xc2, 0x2019, 64 * 1024, 512, FL_ERASE_4K | FL_ERASE_32K | FL_ENABLE_4B_ADDR },
|
2013-08-28 14:49:36 +00:00
|
|
|
{ "s25fl032", 0x01, 0x0215, 64 * 1024, 64, FL_NONE },
|
|
|
|
{ "s25fl064", 0x01, 0x0216, 64 * 1024, 128, FL_NONE },
|
2012-09-25 22:12:07 +00:00
|
|
|
{ "s25fl128", 0x01, 0x2018, 64 * 1024, 256, FL_NONE },
|
2015-11-05 03:13:10 +00:00
|
|
|
{ "s25fl256s", 0x01, 0x0219, 64 * 1024, 512, FL_NONE },
|
2017-10-30 02:31:08 +00:00
|
|
|
{ "SST25VF010A", 0xbf, 0x2549, 4 * 1024, 32, FL_ERASE_4K | FL_ERASE_32K },
|
2012-09-25 22:12:07 +00:00
|
|
|
{ "SST25VF032B", 0xbf, 0x254a, 64 * 1024, 64, FL_ERASE_4K | FL_ERASE_32K },
|
2013-06-08 20:12:14 +00:00
|
|
|
|
|
|
|
/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
|
|
|
|
{ "w25x32", 0xef, 0x3016, 64 * 1024, 64, FL_ERASE_4K },
|
2016-05-26 01:19:13 +00:00
|
|
|
{ "w25x64", 0xef, 0x3017, 64 * 1024, 128, FL_ERASE_4K },
|
2012-09-25 22:12:07 +00:00
|
|
|
{ "w25q32", 0xef, 0x4016, 64 * 1024, 64, FL_ERASE_4K },
|
|
|
|
{ "w25q64", 0xef, 0x4017, 64 * 1024, 128, FL_ERASE_4K },
|
|
|
|
{ "w25q64bv", 0xef, 0x4017, 64 * 1024, 128, FL_ERASE_4K },
|
2013-06-08 20:12:14 +00:00
|
|
|
{ "w25q128", 0xef, 0x4018, 64 * 1024, 256, FL_ERASE_4K },
|
|
|
|
{ "w25q256", 0xef, 0x4019, 64 * 1024, 512, FL_ERASE_4K },
|
2016-06-08 14:22:16 +00:00
|
|
|
|
|
|
|
/* Atmel */
|
|
|
|
{ "at25df641", 0x1f, 0x4800, 64 * 1024, 128, FL_ERASE_4K },
|
2016-07-21 15:48:41 +00:00
|
|
|
|
|
|
|
/* GigaDevice */
|
|
|
|
{ "gd25q64", 0xc8, 0x4017, 64 * 1024, 128, FL_ERASE_4K },
|
2019-10-25 17:56:24 +00:00
|
|
|
{ "gd25q128", 0xc8, 0x4018, 64 * 1024, 256, FL_ERASE_4K },
|
2009-05-18 23:20:56 +00:00
|
|
|
};
|
|
|
|
|
2018-03-18 17:47:57 +00:00
|
|
|
static int
|
|
|
|
mx25l_wait_for_device_ready(struct mx25l_softc *sc)
|
2009-05-18 23:20:56 +00:00
|
|
|
{
|
|
|
|
uint8_t txBuf[2], rxBuf[2];
|
|
|
|
struct spi_command cmd;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
|
2018-03-18 17:47:57 +00:00
|
|
|
do {
|
|
|
|
txBuf[0] = CMD_READ_STATUS;
|
|
|
|
cmd.tx_cmd = txBuf;
|
|
|
|
cmd.rx_cmd = rxBuf;
|
|
|
|
cmd.rx_cmd_sz = 2;
|
|
|
|
cmd.tx_cmd_sz = 2;
|
|
|
|
err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd);
|
|
|
|
} while (err == 0 && (rxBuf[1] & STATUS_WIP));
|
2009-05-18 23:20:56 +00:00
|
|
|
|
2018-03-18 17:47:57 +00:00
|
|
|
return (err);
|
2009-05-18 23:20:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct mx25l_flash_ident*
|
|
|
|
mx25l_get_device_ident(struct mx25l_softc *sc)
|
|
|
|
{
|
|
|
|
uint8_t txBuf[8], rxBuf[8];
|
|
|
|
struct spi_command cmd;
|
|
|
|
uint8_t manufacturer_id;
|
|
|
|
uint16_t dev_id;
|
|
|
|
int err, i;
|
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
memset(txBuf, 0, sizeof(txBuf));
|
|
|
|
memset(rxBuf, 0, sizeof(rxBuf));
|
|
|
|
|
|
|
|
txBuf[0] = CMD_READ_IDENT;
|
|
|
|
cmd.tx_cmd = &txBuf;
|
|
|
|
cmd.rx_cmd = &rxBuf;
|
|
|
|
/*
|
|
|
|
* Some compatible devices has extended two-bytes ID
|
|
|
|
* We'll use only manufacturer/deviceid atm
|
|
|
|
*/
|
|
|
|
cmd.tx_cmd_sz = 4;
|
|
|
|
cmd.rx_cmd_sz = 4;
|
2018-03-18 17:25:23 +00:00
|
|
|
err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd);
|
2009-05-18 23:20:56 +00:00
|
|
|
if (err)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
manufacturer_id = rxBuf[1];
|
|
|
|
dev_id = (rxBuf[2] << 8) | (rxBuf[3]);
|
|
|
|
|
2018-03-18 17:47:57 +00:00
|
|
|
for (i = 0; i < nitems(flash_devices); i++) {
|
2009-05-18 23:20:56 +00:00
|
|
|
if ((flash_devices[i].manufacturer_id == manufacturer_id) &&
|
|
|
|
(flash_devices[i].device_id == dev_id))
|
|
|
|
return &flash_devices[i];
|
|
|
|
}
|
|
|
|
|
2018-03-18 17:25:23 +00:00
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"Unknown SPI flash device. Vendor: %02x, device id: %04x\n",
|
2009-05-18 23:20:56 +00:00
|
|
|
manufacturer_id, dev_id);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
2018-03-18 17:47:57 +00:00
|
|
|
static int
|
2018-03-18 17:25:23 +00:00
|
|
|
mx25l_set_writable(struct mx25l_softc *sc, int writable)
|
2009-10-25 08:43:38 +00:00
|
|
|
{
|
|
|
|
uint8_t txBuf[1], rxBuf[1];
|
|
|
|
struct spi_command cmd;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
memset(txBuf, 0, sizeof(txBuf));
|
|
|
|
memset(rxBuf, 0, sizeof(rxBuf));
|
|
|
|
|
|
|
|
txBuf[0] = writable ? CMD_WRITE_ENABLE : CMD_WRITE_DISABLE;
|
|
|
|
cmd.tx_cmd = txBuf;
|
|
|
|
cmd.rx_cmd = rxBuf;
|
|
|
|
cmd.rx_cmd_sz = 1;
|
|
|
|
cmd.tx_cmd_sz = 1;
|
2018-03-18 17:25:23 +00:00
|
|
|
err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd);
|
2018-03-18 17:47:57 +00:00
|
|
|
return (err);
|
2009-10-25 08:43:38 +00:00
|
|
|
}
|
|
|
|
|
2018-03-18 17:47:57 +00:00
|
|
|
static int
|
2018-03-18 18:37:47 +00:00
|
|
|
mx25l_erase_cmd(struct mx25l_softc *sc, off_t sector)
|
2009-10-25 08:43:38 +00:00
|
|
|
{
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
uint8_t txBuf[5], rxBuf[5];
|
2009-10-25 08:43:38 +00:00
|
|
|
struct spi_command cmd;
|
|
|
|
int err;
|
|
|
|
|
2018-03-18 17:47:57 +00:00
|
|
|
if ((err = mx25l_set_writable(sc, 1)) != 0)
|
|
|
|
return (err);
|
2009-10-25 08:43:38 +00:00
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
memset(txBuf, 0, sizeof(txBuf));
|
|
|
|
memset(rxBuf, 0, sizeof(rxBuf));
|
|
|
|
|
|
|
|
cmd.tx_cmd = txBuf;
|
|
|
|
cmd.rx_cmd = rxBuf;
|
2018-03-18 18:37:47 +00:00
|
|
|
|
|
|
|
if (sc->sc_flags & FL_ERASE_4K)
|
|
|
|
txBuf[0] = CMD_BLOCK_4K_ERASE;
|
|
|
|
else if (sc->sc_flags & FL_ERASE_32K)
|
|
|
|
txBuf[0] = CMD_BLOCK_32K_ERASE;
|
|
|
|
else
|
|
|
|
txBuf[0] = CMD_SECTOR_ERASE;
|
|
|
|
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
|
|
|
|
cmd.rx_cmd_sz = 5;
|
|
|
|
cmd.tx_cmd_sz = 5;
|
|
|
|
txBuf[1] = ((sector >> 24) & 0xff);
|
|
|
|
txBuf[2] = ((sector >> 16) & 0xff);
|
|
|
|
txBuf[3] = ((sector >> 8) & 0xff);
|
|
|
|
txBuf[4] = (sector & 0xff);
|
|
|
|
} else {
|
|
|
|
cmd.rx_cmd_sz = 4;
|
|
|
|
cmd.tx_cmd_sz = 4;
|
|
|
|
txBuf[1] = ((sector >> 16) & 0xff);
|
|
|
|
txBuf[2] = ((sector >> 8) & 0xff);
|
|
|
|
txBuf[3] = (sector & 0xff);
|
|
|
|
}
|
2018-03-18 17:47:57 +00:00
|
|
|
if ((err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd)) != 0)
|
|
|
|
return (err);
|
|
|
|
err = mx25l_wait_for_device_ready(sc);
|
|
|
|
return (err);
|
2009-10-25 08:43:38 +00:00
|
|
|
}
|
|
|
|
|
2009-11-18 22:14:36 +00:00
|
|
|
static int
|
2018-03-18 17:25:23 +00:00
|
|
|
mx25l_write(struct mx25l_softc *sc, off_t offset, caddr_t data, off_t count)
|
2009-11-18 22:14:36 +00:00
|
|
|
{
|
|
|
|
uint8_t txBuf[8], rxBuf[8];
|
|
|
|
struct spi_command cmd;
|
2018-03-18 16:36:14 +00:00
|
|
|
off_t bytes_to_write;
|
2009-11-18 22:14:36 +00:00
|
|
|
int err = 0;
|
|
|
|
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
|
|
|
|
cmd.tx_cmd_sz = 5;
|
|
|
|
cmd.rx_cmd_sz = 5;
|
|
|
|
} else {
|
|
|
|
cmd.tx_cmd_sz = 4;
|
|
|
|
cmd.rx_cmd_sz = 4;
|
|
|
|
}
|
2009-11-18 22:14:36 +00:00
|
|
|
|
|
|
|
/*
|
2018-03-18 16:10:14 +00:00
|
|
|
* Writes must be aligned to the erase sectorsize, since blocks are
|
|
|
|
* fully erased before they're written to.
|
2009-11-18 22:14:36 +00:00
|
|
|
*/
|
2018-03-18 18:37:47 +00:00
|
|
|
if (count % sc->sc_erasesize != 0 || offset % sc->sc_erasesize != 0)
|
2011-02-16 20:07:44 +00:00
|
|
|
return (EIO);
|
2009-11-18 22:14:36 +00:00
|
|
|
|
|
|
|
/*
|
2018-03-18 16:36:14 +00:00
|
|
|
* Maximum write size for CMD_PAGE_PROGRAM is FLASH_PAGE_SIZE, so loop
|
|
|
|
* to write chunks of FLASH_PAGE_SIZE bytes each.
|
2009-11-18 22:14:36 +00:00
|
|
|
*/
|
2018-03-18 16:36:14 +00:00
|
|
|
while (count != 0) {
|
|
|
|
/* If we crossed a sector boundary, erase the next sector. */
|
2018-03-18 18:37:47 +00:00
|
|
|
if (((offset) % sc->sc_erasesize) == 0) {
|
|
|
|
err = mx25l_erase_cmd(sc, offset);
|
2018-03-18 17:47:57 +00:00
|
|
|
if (err)
|
|
|
|
break;
|
|
|
|
}
|
2009-11-18 22:14:36 +00:00
|
|
|
|
|
|
|
txBuf[0] = CMD_PAGE_PROGRAM;
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
|
2018-03-18 16:36:14 +00:00
|
|
|
txBuf[1] = (offset >> 24) & 0xff;
|
|
|
|
txBuf[2] = (offset >> 16) & 0xff;
|
|
|
|
txBuf[3] = (offset >> 8) & 0xff;
|
|
|
|
txBuf[4] = offset & 0xff;
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
} else {
|
2018-03-18 16:36:14 +00:00
|
|
|
txBuf[1] = (offset >> 16) & 0xff;
|
|
|
|
txBuf[2] = (offset >> 8) & 0xff;
|
|
|
|
txBuf[3] = offset & 0xff;
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
}
|
2009-11-18 22:14:36 +00:00
|
|
|
|
2018-03-18 16:36:14 +00:00
|
|
|
bytes_to_write = MIN(FLASH_PAGE_SIZE, count);
|
2009-11-18 22:14:36 +00:00
|
|
|
cmd.tx_cmd = txBuf;
|
|
|
|
cmd.rx_cmd = rxBuf;
|
2018-03-18 16:36:14 +00:00
|
|
|
cmd.tx_data = data;
|
2018-03-18 15:56:10 +00:00
|
|
|
cmd.rx_data = sc->sc_dummybuf;
|
2018-03-18 16:36:14 +00:00
|
|
|
cmd.tx_data_sz = (uint32_t)bytes_to_write;
|
|
|
|
cmd.rx_data_sz = (uint32_t)bytes_to_write;
|
2009-11-18 22:14:36 +00:00
|
|
|
|
|
|
|
/*
|
2018-03-18 16:36:14 +00:00
|
|
|
* Each completed write operation resets WEL (write enable
|
|
|
|
* latch) to disabled state, so we re-enable it here.
|
2009-11-18 22:14:36 +00:00
|
|
|
*/
|
2018-03-18 17:47:57 +00:00
|
|
|
if ((err = mx25l_wait_for_device_ready(sc)) != 0)
|
|
|
|
break;
|
|
|
|
if ((err = mx25l_set_writable(sc, 1)) != 0)
|
|
|
|
break;
|
2009-11-18 22:14:36 +00:00
|
|
|
|
2018-03-18 17:25:23 +00:00
|
|
|
err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd);
|
2018-03-18 17:47:57 +00:00
|
|
|
if (err != 0)
|
|
|
|
break;
|
|
|
|
err = mx25l_wait_for_device_ready(sc);
|
2009-11-18 22:14:36 +00:00
|
|
|
if (err)
|
|
|
|
break;
|
|
|
|
|
2018-03-18 16:36:14 +00:00
|
|
|
data += bytes_to_write;
|
|
|
|
offset += bytes_to_write;
|
|
|
|
count -= bytes_to_write;
|
2009-11-18 22:14:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (err);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2018-03-18 17:25:23 +00:00
|
|
|
mx25l_read(struct mx25l_softc *sc, off_t offset, caddr_t data, off_t count)
|
2009-11-18 22:14:36 +00:00
|
|
|
{
|
|
|
|
uint8_t txBuf[8], rxBuf[8];
|
|
|
|
struct spi_command cmd;
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
/*
|
2018-03-18 16:36:14 +00:00
|
|
|
* Enforce that reads are aligned to the disk sectorsize, not the
|
|
|
|
* erase sectorsize. In this way, smaller read IO is possible,
|
|
|
|
* dramatically speeding up filesystem/geom_compress access.
|
2009-11-18 22:14:36 +00:00
|
|
|
*/
|
2018-03-18 16:36:14 +00:00
|
|
|
if (count % sc->sc_disk->d_sectorsize != 0 ||
|
|
|
|
offset % sc->sc_disk->d_sectorsize != 0)
|
2011-02-16 20:07:44 +00:00
|
|
|
return (EIO);
|
2009-11-18 22:14:36 +00:00
|
|
|
|
|
|
|
txBuf[0] = CMD_FAST_READ;
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
|
|
|
|
cmd.tx_cmd_sz = 6;
|
|
|
|
cmd.rx_cmd_sz = 6;
|
|
|
|
|
2018-03-18 16:36:14 +00:00
|
|
|
txBuf[1] = (offset >> 24) & 0xff;
|
|
|
|
txBuf[2] = (offset >> 16) & 0xff;
|
|
|
|
txBuf[3] = (offset >> 8) & 0xff;
|
|
|
|
txBuf[4] = offset & 0xff;
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
/* Dummy byte */
|
|
|
|
txBuf[5] = 0;
|
|
|
|
} else {
|
|
|
|
cmd.tx_cmd_sz = 5;
|
|
|
|
cmd.rx_cmd_sz = 5;
|
|
|
|
|
2018-03-18 16:36:14 +00:00
|
|
|
txBuf[1] = (offset >> 16) & 0xff;
|
|
|
|
txBuf[2] = (offset >> 8) & 0xff;
|
|
|
|
txBuf[3] = offset & 0xff;
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
/* Dummy byte */
|
|
|
|
txBuf[4] = 0;
|
|
|
|
}
|
2009-11-18 22:14:36 +00:00
|
|
|
|
|
|
|
cmd.tx_cmd = txBuf;
|
|
|
|
cmd.rx_cmd = rxBuf;
|
|
|
|
cmd.tx_data = data;
|
|
|
|
cmd.rx_data = data;
|
2018-03-18 16:36:14 +00:00
|
|
|
cmd.tx_data_sz = count;
|
2009-11-18 22:14:36 +00:00
|
|
|
cmd.rx_data_sz = count;
|
|
|
|
|
2018-03-18 17:25:23 +00:00
|
|
|
err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd);
|
2009-11-18 22:14:36 +00:00
|
|
|
return (err);
|
|
|
|
}
|
|
|
|
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
static int
|
2018-03-18 17:25:23 +00:00
|
|
|
mx25l_set_4b_mode(struct mx25l_softc *sc, uint8_t command)
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
{
|
|
|
|
uint8_t txBuf[1], rxBuf[1];
|
|
|
|
struct spi_command cmd;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
memset(txBuf, 0, sizeof(txBuf));
|
|
|
|
memset(rxBuf, 0, sizeof(rxBuf));
|
|
|
|
|
|
|
|
cmd.tx_cmd_sz = cmd.rx_cmd_sz = 1;
|
|
|
|
|
|
|
|
cmd.tx_cmd = txBuf;
|
|
|
|
cmd.rx_cmd = rxBuf;
|
|
|
|
|
|
|
|
txBuf[0] = command;
|
|
|
|
|
2018-03-18 17:47:57 +00:00
|
|
|
if ((err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd)) == 0)
|
|
|
|
err = mx25l_wait_for_device_ready(sc);
|
Enable 4-byte address support for the mx25l family of SPI flash devices.
Introduce 2 new flags:
- FL_ENABLE_4B_ADDR (forces the use of 4-byte addresses)
- FL_DISABLE_4B_ADDR (forces the use of 3-byte addresses)
If an SPI flash chip is defined with FL_ENABLE_4B_ADDR in its flags,
then an 'Enter 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 4-byte
addresses.
If an SPI flash chip is defined with FL_DISABLE_4B_ADDR in its flags,
then an 'Exit 4-byte mode' command is sent to the chip at attach time
and, later, all commands that require addressing are issued with 3-byte
addresses.
For chips that do not have any of these flags defined the behaviour is
unchanged.
This change also adds support for the MX25L25735F and MX25L25635E chips
(vendor id 0xc2, device id 0x2019), which support 4-byte mode and enables
4-byte mode for them. These are 256Mbit devices (32MiB) and, as such, can
only be fully addressed by using 4-byte addresses.
Approved by: adrian (mentor)
Sponsored by: Smartcom - Bulgaria AD
Differential Revision: https://reviews.freebsd.org/D5808
2016-04-04 06:55:48 +00:00
|
|
|
|
|
|
|
return (err);
|
|
|
|
}
|
|
|
|
|
2016-04-17 02:05:45 +00:00
|
|
|
#ifdef FDT
|
2016-04-15 15:26:31 +00:00
|
|
|
static struct ofw_compat_data compat_data[] = {
|
|
|
|
{ "st,m25p", 1 },
|
|
|
|
{ "jedec,spi-nor", 1 },
|
|
|
|
{ NULL, 0 },
|
|
|
|
};
|
2016-04-17 02:05:45 +00:00
|
|
|
#endif
|
2016-04-15 15:26:31 +00:00
|
|
|
|
2009-05-18 23:20:56 +00:00
|
|
|
static int
|
|
|
|
mx25l_probe(device_t dev)
|
|
|
|
{
|
2016-03-30 17:00:33 +00:00
|
|
|
#ifdef FDT
|
2016-04-20 14:33:00 +00:00
|
|
|
int i;
|
|
|
|
|
2016-03-30 17:00:33 +00:00
|
|
|
if (!ofw_bus_status_okay(dev))
|
|
|
|
return (ENXIO);
|
2016-04-20 14:33:00 +00:00
|
|
|
|
|
|
|
/* First try to match the compatible property to the compat_data */
|
|
|
|
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 1)
|
|
|
|
goto found;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Next, try to find a compatible device using the names in the
|
|
|
|
* flash_devices structure
|
|
|
|
*/
|
|
|
|
for (i = 0; i < nitems(flash_devices); i++)
|
|
|
|
if (ofw_bus_is_compatible(dev, flash_devices[i].name))
|
|
|
|
goto found;
|
|
|
|
|
|
|
|
return (ENXIO);
|
|
|
|
found:
|
2016-03-30 17:00:33 +00:00
|
|
|
#endif
|
2009-05-18 23:20:56 +00:00
|
|
|
device_set_desc(dev, "M25Pxx Flash Family");
|
2016-03-30 17:00:33 +00:00
|
|
|
|
2009-05-18 23:20:56 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
mx25l_attach(device_t dev)
|
|
|
|
{
|
|
|
|
struct mx25l_softc *sc;
|
|
|
|
struct mx25l_flash_ident *ident;
|
2018-03-18 17:47:57 +00:00
|
|
|
int err;
|
2009-05-18 23:20:56 +00:00
|
|
|
|
|
|
|
sc = device_get_softc(dev);
|
|
|
|
sc->sc_dev = dev;
|
2018-03-18 17:25:23 +00:00
|
|
|
sc->sc_parent = device_get_parent(sc->sc_dev);
|
|
|
|
|
2009-05-18 23:20:56 +00:00
|
|
|
M25PXX_LOCK_INIT(sc);
|
|
|
|
|
|
|
|
ident = mx25l_get_device_ident(sc);
|
|
|
|
if (ident == NULL)
|
|
|
|
return (ENXIO);
|
|
|
|
|
2018-03-18 17:47:57 +00:00
|
|
|
if ((err = mx25l_wait_for_device_ready(sc)) != 0)
|
|
|
|
return (err);
|
|
|
|
|
2018-03-18 18:37:47 +00:00
|
|
|
sc->sc_flags = ident->flags;
|
|
|
|
|
|
|
|
if (sc->sc_flags & FL_ERASE_4K)
|
|
|
|
sc->sc_erasesize = 4 * 1024;
|
|
|
|
else if (sc->sc_flags & FL_ERASE_32K)
|
|
|
|
sc->sc_erasesize = 32 * 1024;
|
|
|
|
else
|
|
|
|
sc->sc_erasesize = ident->sectorsize;
|
|
|
|
|
2018-03-18 17:47:57 +00:00
|
|
|
if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
|
|
|
|
if ((err = mx25l_set_4b_mode(sc, CMD_ENTER_4B_MODE)) != 0)
|
|
|
|
return (err);
|
|
|
|
} else if (sc->sc_flags & FL_DISABLE_4B_ADDR) {
|
|
|
|
if ((err = mx25l_set_4b_mode(sc, CMD_EXIT_4B_MODE)) != 0)
|
|
|
|
return (err);
|
|
|
|
}
|
2009-05-18 23:20:56 +00:00
|
|
|
|
|
|
|
sc->sc_disk = disk_alloc();
|
|
|
|
sc->sc_disk->d_open = mx25l_open;
|
|
|
|
sc->sc_disk->d_close = mx25l_close;
|
|
|
|
sc->sc_disk->d_strategy = mx25l_strategy;
|
2016-01-22 03:15:53 +00:00
|
|
|
sc->sc_disk->d_getattr = mx25l_getattr;
|
2009-05-18 23:20:56 +00:00
|
|
|
sc->sc_disk->d_ioctl = mx25l_ioctl;
|
2019-03-10 18:48:08 +00:00
|
|
|
sc->sc_disk->d_name = "flash/spi";
|
2009-05-18 23:20:56 +00:00
|
|
|
sc->sc_disk->d_drv1 = sc;
|
|
|
|
sc->sc_disk->d_maxsize = DFLTPHYS;
|
2011-02-16 20:07:44 +00:00
|
|
|
sc->sc_disk->d_sectorsize = MX25L_SECTORSIZE;
|
2009-05-18 23:20:56 +00:00
|
|
|
sc->sc_disk->d_mediasize = ident->sectorsize * ident->sectorcount;
|
2018-03-18 18:37:47 +00:00
|
|
|
sc->sc_disk->d_stripesize = sc->sc_erasesize;
|
2009-05-18 23:20:56 +00:00
|
|
|
sc->sc_disk->d_unit = device_get_unit(sc->sc_dev);
|
|
|
|
sc->sc_disk->d_dump = NULL; /* NB: no dumps */
|
2018-03-18 18:58:47 +00:00
|
|
|
strlcpy(sc->sc_disk->d_descr, ident->name,
|
|
|
|
sizeof(sc->sc_disk->d_descr));
|
2009-05-18 23:20:56 +00:00
|
|
|
|
|
|
|
disk_create(sc->sc_disk, DISK_VERSION);
|
|
|
|
bioq_init(&sc->sc_bio_queue);
|
|
|
|
|
|
|
|
kproc_create(&mx25l_task, sc, &sc->sc_p, 0, 0, "task: mx25l flash");
|
2018-02-24 16:28:45 +00:00
|
|
|
sc->sc_taskstate = TSTATE_RUNNING;
|
|
|
|
|
2018-03-18 18:58:47 +00:00
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"device type %s, size %dK in %d sectors of %dK, erase size %dK\n",
|
|
|
|
ident->name,
|
|
|
|
ident->sectorcount * ident->sectorsize / 1024,
|
|
|
|
ident->sectorcount, ident->sectorsize / 1024,
|
|
|
|
sc->sc_erasesize / 1024);
|
2009-05-18 23:20:56 +00:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
mx25l_detach(device_t dev)
|
|
|
|
{
|
2018-02-24 16:28:45 +00:00
|
|
|
struct mx25l_softc *sc;
|
|
|
|
int err;
|
2009-05-18 23:20:56 +00:00
|
|
|
|
2018-02-24 16:28:45 +00:00
|
|
|
sc = device_get_softc(dev);
|
|
|
|
err = 0;
|
|
|
|
|
|
|
|
M25PXX_LOCK(sc);
|
|
|
|
if (sc->sc_taskstate == TSTATE_RUNNING) {
|
|
|
|
sc->sc_taskstate = TSTATE_STOPPING;
|
|
|
|
wakeup(sc);
|
|
|
|
while (err == 0 && sc->sc_taskstate != TSTATE_STOPPED) {
|
|
|
|
err = msleep(sc, &sc->sc_mtx, 0, "mx25dt", hz * 3);
|
|
|
|
if (err != 0) {
|
|
|
|
sc->sc_taskstate = TSTATE_RUNNING;
|
2018-03-18 17:25:23 +00:00
|
|
|
device_printf(sc->sc_dev,
|
2018-02-24 16:28:45 +00:00
|
|
|
"Failed to stop queue task\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
M25PXX_UNLOCK(sc);
|
|
|
|
|
|
|
|
if (err == 0 && sc->sc_taskstate == TSTATE_STOPPED) {
|
|
|
|
disk_destroy(sc->sc_disk);
|
|
|
|
bioq_flush(&sc->sc_bio_queue, NULL, ENXIO);
|
|
|
|
M25PXX_LOCK_DESTROY(sc);
|
|
|
|
}
|
|
|
|
return (err);
|
2009-05-18 23:20:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
mx25l_open(struct disk *dp)
|
|
|
|
{
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
mx25l_close(struct disk *dp)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
mx25l_ioctl(struct disk *dp, u_long cmd, void *data, int fflag,
|
|
|
|
struct thread *td)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mx25l_strategy(struct bio *bp)
|
|
|
|
{
|
|
|
|
struct mx25l_softc *sc;
|
|
|
|
|
|
|
|
sc = (struct mx25l_softc *)bp->bio_disk->d_drv1;
|
|
|
|
M25PXX_LOCK(sc);
|
|
|
|
bioq_disksort(&sc->sc_bio_queue, bp);
|
|
|
|
wakeup(sc);
|
|
|
|
M25PXX_UNLOCK(sc);
|
|
|
|
}
|
|
|
|
|
2016-01-22 03:15:53 +00:00
|
|
|
static int
|
|
|
|
mx25l_getattr(struct bio *bp)
|
|
|
|
{
|
|
|
|
struct mx25l_softc *sc;
|
|
|
|
device_t dev;
|
|
|
|
|
|
|
|
if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL)
|
|
|
|
return (ENXIO);
|
|
|
|
|
|
|
|
sc = bp->bio_disk->d_drv1;
|
|
|
|
dev = sc->sc_dev;
|
|
|
|
|
|
|
|
if (strcmp(bp->bio_attribute, "SPI::device") == 0) {
|
|
|
|
if (bp->bio_length != sizeof(dev))
|
|
|
|
return (EFAULT);
|
|
|
|
bcopy(&dev, bp->bio_data, sizeof(dev));
|
|
|
|
} else
|
|
|
|
return (-1);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2009-05-18 23:20:56 +00:00
|
|
|
static void
|
|
|
|
mx25l_task(void *arg)
|
|
|
|
{
|
|
|
|
struct mx25l_softc *sc = (struct mx25l_softc*)arg;
|
|
|
|
struct bio *bp;
|
2009-11-18 22:14:36 +00:00
|
|
|
device_t dev;
|
2009-05-18 23:20:56 +00:00
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
dev = sc->sc_dev;
|
|
|
|
M25PXX_LOCK(sc);
|
|
|
|
do {
|
2018-02-24 16:28:45 +00:00
|
|
|
if (sc->sc_taskstate == TSTATE_STOPPING) {
|
|
|
|
sc->sc_taskstate = TSTATE_STOPPED;
|
|
|
|
M25PXX_UNLOCK(sc);
|
|
|
|
wakeup(sc);
|
|
|
|
kproc_exit(0);
|
|
|
|
}
|
2009-05-18 23:20:56 +00:00
|
|
|
bp = bioq_first(&sc->sc_bio_queue);
|
|
|
|
if (bp == NULL)
|
2018-02-24 16:28:45 +00:00
|
|
|
msleep(sc, &sc->sc_mtx, PRIBIO, "mx25jq", 0);
|
2009-05-18 23:20:56 +00:00
|
|
|
} while (bp == NULL);
|
|
|
|
bioq_remove(&sc->sc_bio_queue, bp);
|
|
|
|
M25PXX_UNLOCK(sc);
|
|
|
|
|
2009-11-18 22:14:36 +00:00
|
|
|
switch (bp->bio_cmd) {
|
|
|
|
case BIO_READ:
|
2018-03-18 17:25:23 +00:00
|
|
|
bp->bio_error = mx25l_read(sc, bp->bio_offset,
|
2009-11-18 22:14:36 +00:00
|
|
|
bp->bio_data, bp->bio_bcount);
|
|
|
|
break;
|
|
|
|
case BIO_WRITE:
|
2018-03-18 17:25:23 +00:00
|
|
|
bp->bio_error = mx25l_write(sc, bp->bio_offset,
|
2009-11-18 22:14:36 +00:00
|
|
|
bp->bio_data, bp->bio_bcount);
|
|
|
|
break;
|
|
|
|
default:
|
2020-02-07 09:22:08 +00:00
|
|
|
bp->bio_error = EOPNOTSUPP;
|
2009-11-18 22:14:36 +00:00
|
|
|
}
|
2009-05-18 23:20:56 +00:00
|
|
|
|
2009-10-25 08:43:38 +00:00
|
|
|
|
2009-05-18 23:20:56 +00:00
|
|
|
biodone(bp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static devclass_t mx25l_devclass;
|
|
|
|
|
|
|
|
static device_method_t mx25l_methods[] = {
|
|
|
|
/* Device interface */
|
|
|
|
DEVMETHOD(device_probe, mx25l_probe),
|
|
|
|
DEVMETHOD(device_attach, mx25l_attach),
|
|
|
|
DEVMETHOD(device_detach, mx25l_detach),
|
|
|
|
|
|
|
|
{ 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static driver_t mx25l_driver = {
|
|
|
|
"mx25l",
|
|
|
|
mx25l_methods,
|
|
|
|
sizeof(struct mx25l_softc),
|
|
|
|
};
|
|
|
|
|
|
|
|
DRIVER_MODULE(mx25l, spibus, mx25l_driver, mx25l_devclass, 0, 0);
|
2018-02-20 03:51:09 +00:00
|
|
|
MODULE_DEPEND(mx25l, spibus, 1, 1, 1);
|
2018-06-14 19:01:40 +00:00
|
|
|
#ifdef FDT
|
2019-02-26 22:52:08 +00:00
|
|
|
MODULE_DEPEND(mx25l, fdt_slicer, 1, 1, 1);
|
2019-05-23 15:59:50 +00:00
|
|
|
SPIBUS_FDT_PNP_INFO(compat_data);
|
2018-06-14 19:01:40 +00:00
|
|
|
#endif
|