summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2010-09-05 20:04:02 +0000
committermav <mav@FreeBSD.org>2010-09-05 20:04:02 +0000
commitd23fcb99b77450a25e5998f50b6986576381c3ea (patch)
tree4deb41ee337cfbe738336b685e94cce24494c9e0
parent90db0224ffc7d244859d788e9107f74418a3e22d (diff)
downloadFreeBSD-src-d23fcb99b77450a25e5998f50b6986576381c3ea.zip
FreeBSD-src-d23fcb99b77450a25e5998f50b6986576381c3ea.tar.gz
Add support for the Sharp/Micron flash chips to powermac_mvram(4).
Tested on PowerMac G4 AGP. Reviewed by: nwhitehorn
-rw-r--r--share/man/man4/man4.powerpc/powermac_nvram.47
-rw-r--r--sys/dev/powermac_nvram/powermac_nvram.c110
-rw-r--r--sys/dev/powermac_nvram/powermac_nvramvar.h13
3 files changed, 118 insertions, 12 deletions
diff --git a/share/man/man4/man4.powerpc/powermac_nvram.4 b/share/man/man4/man4.powerpc/powermac_nvram.4
index 0340422..9aae920 100644
--- a/share/man/man4/man4.powerpc/powermac_nvram.4
+++ b/share/man/man4/man4.powerpc/powermac_nvram.4
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 1, 2006
+.Dd September 5, 2010
.Dt POWERMAC_NVRAM 4 powerpc
.Os
.Sh NAME
@@ -63,8 +63,3 @@ The
.Nm
driver was written by
.An Maxim Sobolev Aq sobomax@FreeBSD.org .
-.Sh BUGS
-Currently, the
-.Nm
-driver only supports systems equipped with an AMD flash part and is only
-tested on Apple G4-based Mac Mini machines.
diff --git a/sys/dev/powermac_nvram/powermac_nvram.c b/sys/dev/powermac_nvram/powermac_nvram.c
index 22174f9..0c7949f 100644
--- a/sys/dev/powermac_nvram/powermac_nvram.c
+++ b/sys/dev/powermac_nvram/powermac_nvram.c
@@ -115,7 +115,10 @@ powermac_nvram_probe(device_t dev)
if (type == NULL || compatible == NULL)
return ENXIO;
- if (strcmp(type, "nvram") != 0 || strcmp(compatible, "amd-0137") != 0)
+ if (strcmp(type, "nvram") != 0)
+ return ENXIO;
+ if (strcmp(compatible, "amd-0137") != 0 &&
+ strcmp(compatible, "nvram,flash") != 0)
return ENXIO;
device_set_desc(dev, "Apple NVRAM");
@@ -126,6 +129,7 @@ static int
powermac_nvram_attach(device_t dev)
{
struct powermac_nvram_softc *sc;
+ const char *compatible;
phandle_t node;
u_int32_t reg[3];
int gen0, gen1, i;
@@ -139,6 +143,12 @@ powermac_nvram_attach(device_t dev)
sc->sc_dev = dev;
sc->sc_node = node;
+ compatible = ofw_bus_get_compat(dev);
+ if (strcmp(compatible, "amd-0137") == 0)
+ sc->sc_type = FLASH_TYPE_AMD;
+ else
+ sc->sc_type = FLASH_TYPE_SM;
+
/*
* Find which byte of reg corresponds to the 32-bit physical address.
* We should probably read #address-cells from /chosen instead.
@@ -342,7 +352,7 @@ adler_checksum(uint8_t *data, int len)
#define OUTB_DELAY(a, v) outb(a, v); DELAY(1);
static int
-wait_operation_complete(uint8_t *bank)
+wait_operation_complete_amd(uint8_t *bank)
{
int i;
@@ -353,7 +363,7 @@ wait_operation_complete(uint8_t *bank)
}
static int
-erase_bank(device_t dev, uint8_t *bank)
+erase_bank_amd(device_t dev, uint8_t *bank)
{
unsigned int i;
@@ -368,7 +378,7 @@ erase_bank(device_t dev, uint8_t *bank)
OUTB_DELAY(bank + 0x2aa, 0x55);
OUTB_DELAY(bank, 0x30);
- if (wait_operation_complete(bank) != 0) {
+ if (wait_operation_complete_amd(bank) != 0) {
device_printf(dev, "flash erase timeout\n");
return -1;
}
@@ -386,7 +396,7 @@ erase_bank(device_t dev, uint8_t *bank)
}
static int
-write_bank(device_t dev, uint8_t *bank, uint8_t *data)
+write_bank_amd(device_t dev, uint8_t *bank, uint8_t *data)
{
unsigned int i;
@@ -399,7 +409,7 @@ write_bank(device_t dev, uint8_t *bank, uint8_t *data)
/* Write single word */
OUTB_DELAY(bank + 0x555, 0xa0);
OUTB_DELAY(bank + i, data[i]);
- if (wait_operation_complete(bank) != 0) {
+ if (wait_operation_complete_amd(bank) != 0) {
device_printf(dev, "flash write timeout\n");
return -1;
}
@@ -416,3 +426,91 @@ write_bank(device_t dev, uint8_t *bank, uint8_t *data)
}
return 0;
}
+
+static int
+wait_operation_complete_sm(uint8_t *bank)
+{
+ int i;
+
+ for (i = 1000000; i != 0; i--) {
+ outb(bank, SM_FLASH_CMD_READ_STATUS);
+ if (inb(bank) & SM_FLASH_STATUS_DONE)
+ return (0);
+ }
+ return (-1);
+}
+
+static int
+erase_bank_sm(device_t dev, uint8_t *bank)
+{
+ unsigned int i;
+
+ outb(bank, SM_FLASH_CMD_ERASE_SETUP);
+ outb(bank, SM_FLASH_CMD_ERASE_CONFIRM);
+
+ if (wait_operation_complete_sm(bank) != 0) {
+ device_printf(dev, "flash erase timeout\n");
+ return (-1);
+ }
+
+ outb(bank, SM_FLASH_CMD_CLEAR_STATUS);
+ outb(bank, SM_FLASH_CMD_RESET);
+
+ for (i = 0; i < NVRAM_SIZE; i++) {
+ if (bank[i] != 0xff) {
+ device_printf(dev, "flash write has failed\n");
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+static int
+write_bank_sm(device_t dev, uint8_t *bank, uint8_t *data)
+{
+ unsigned int i;
+
+ for (i = 0; i < NVRAM_SIZE; i++) {
+ OUTB_DELAY(bank + i, SM_FLASH_CMD_WRITE_SETUP);
+ outb(bank + i, data[i]);
+ if (wait_operation_complete_sm(bank) != 0) {
+ device_printf(dev, "flash write error/timeout\n");
+ break;
+ }
+ }
+
+ outb(bank, SM_FLASH_CMD_CLEAR_STATUS);
+ outb(bank, SM_FLASH_CMD_RESET);
+
+ for (i = 0; i < NVRAM_SIZE; i++) {
+ if (bank[i] != data[i]) {
+ device_printf(dev, "flash write has failed\n");
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+static int
+erase_bank(device_t dev, uint8_t *bank)
+{
+ struct powermac_nvram_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->sc_type == FLASH_TYPE_AMD)
+ return (erase_bank_amd(dev, bank));
+ else
+ return (erase_bank_sm(dev, bank));
+}
+
+static int
+write_bank(device_t dev, uint8_t *bank, uint8_t *data)
+{
+ struct powermac_nvram_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->sc_type == FLASH_TYPE_AMD)
+ return (write_bank_amd(dev, bank, data));
+ else
+ return (write_bank_sm(dev, bank, data));
+}
diff --git a/sys/dev/powermac_nvram/powermac_nvramvar.h b/sys/dev/powermac_nvram/powermac_nvramvar.h
index 6f4fb26..c326e3c 100644
--- a/sys/dev/powermac_nvram/powermac_nvramvar.h
+++ b/sys/dev/powermac_nvram/powermac_nvramvar.h
@@ -33,6 +33,16 @@
#define CORE99_SIGNATURE 0x5a
+#define SM_FLASH_CMD_ERASE_CONFIRM 0xd0
+#define SM_FLASH_CMD_ERASE_SETUP 0x20
+#define SM_FLASH_CMD_RESET 0xff
+#define SM_FLASH_CMD_WRITE_SETUP 0x40
+#define SM_FLASH_CMD_CLEAR_STATUS 0x50
+#define SM_FLASH_CMD_READ_STATUS 0x70
+
+#define SM_FLASH_STATUS_DONE 0x80
+#define SM_FLASH_STATUS_ERR 0x38
+
#ifdef _KERNEL
struct powermac_nvram_softc {
@@ -44,6 +54,9 @@ struct powermac_nvram_softc {
uint8_t sc_data[NVRAM_SIZE];
struct cdev * sc_cdev;
+ int sc_type;
+#define FLASH_TYPE_SM 0
+#define FLASH_TYPE_AMD 1
int sc_isopen;
int sc_rpos;
int sc_wpos;
OpenPOWER on IntegriCloud