Author: mav
Date: Sun Sep  5 20:04:02 2010
New Revision: 212240
URL: http://svn.freebsd.org/changeset/base/212240

Log:
  Add support for the Sharp/Micron flash chips to powermac_mvram(4).
  Tested on PowerMac G4 AGP.
  
  Reviewed by:  nwhitehorn

Modified:
  head/share/man/man4/man4.powerpc/powermac_nvram.4
  head/sys/dev/powermac_nvram/powermac_nvram.c
  head/sys/dev/powermac_nvram/powermac_nvramvar.h

Modified: head/share/man/man4/man4.powerpc/powermac_nvram.4
==============================================================================
--- head/share/man/man4/man4.powerpc/powermac_nvram.4   Sun Sep  5 19:57:24 
2010        (r212239)
+++ head/share/man/man4/man4.powerpc/powermac_nvram.4   Sun Sep  5 20:04:02 
2010        (r212240)
@@ -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 sobo...@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.

Modified: head/sys/dev/powermac_nvram/powermac_nvram.c
==============================================================================
--- head/sys/dev/powermac_nvram/powermac_nvram.c        Sun Sep  5 19:57:24 
2010        (r212239)
+++ head/sys/dev/powermac_nvram/powermac_nvram.c        Sun Sep  5 20:04:02 
2010        (r212240)
@@ -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, 
                /* 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, 
        }
        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));
+}

Modified: head/sys/dev/powermac_nvram/powermac_nvramvar.h
==============================================================================
--- head/sys/dev/powermac_nvram/powermac_nvramvar.h     Sun Sep  5 19:57:24 
2010        (r212239)
+++ head/sys/dev/powermac_nvram/powermac_nvramvar.h     Sun Sep  5 20:04:02 
2010        (r212240)
@@ -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;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to