Signed-off-by: Amit Uttamchandani <[email protected]>
---
 programmer.h |   1 +
 satamv.c     | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 152 insertions(+)

diff --git a/programmer.h b/programmer.h
index d4d1f90..0259022 100644
--- a/programmer.h
+++ b/programmer.h
@@ -527,6 +527,7 @@ enum spi_controller {
 #if CONFIG_USBBLASTER_SPI == 1
        SPI_CONTROLLER_USBBLASTER,
 #endif
+       SPI_CONTROLLER_SATAMV,
 };
 
 #define MAX_DATA_UNSPECIFIED 0
diff --git a/satamv.c b/satamv.c
index 3065f0c..16787b8 100644
--- a/satamv.c
+++ b/satamv.c
@@ -22,9 +22,15 @@
 #if defined(__i386__) || defined(__x86_64__)
 
 #include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include "flash.h"
 #include "programmer.h"
+#include "chipdrivers.h"
 #include "hwaccess.h"
+#include "spi.h"
+#include <unistd.h>
 
 uint8_t *mv_bar;
 uint16_t mv_iobar;
@@ -32,20 +38,46 @@ uint16_t mv_iobar;
 const struct dev_entry satas_mv[] = {
        /* 88SX6041 and 88SX6042 are the same according to the datasheet. */
        {0x11ab, 0x7042, OK, "Marvell", "88SX7042 PCI-e 4-port SATA-II"},
+       {0x1b4b, 0x9445, OK, "Marvell", "88SE9445 PCI-e 4-port SAS/SATA 6 
Gbps"},
 
        {0},
 };
 
 #define NVRAM_PARAM                    0x1045c
 #define FLASH_PARAM                    0x1046c
+#define EXPANSION_ROM_WINDOW0_REMAP    0x004c8
+#define SPI_FLASH_CONTROL              0x0c800
+#define SPI_FLASH_ADDRESS              0x0c804
+#define SPI_FLASH_WRITE_DATA           0x0c808
+#define SPI_FLASH_READ_DATA            0x0c80c
 #define EXPANSION_ROM_BAR_CONTROL      0x00d2c
 #define PCI_BAR2_CONTROL               0x00c08
 #define GPIO_PORT_CONTROL              0x104f0
 
+static unsigned int spi_write_256_chunksize = 256;
+
+static int satamv_spi_send_command(struct flashctx *flash, unsigned int 
writecnt,
+                                 unsigned int readcnt,
+                                 const unsigned char *writearr,
+                                 unsigned char *readarr);
+static int satamv_spi_write_256(struct flashctx *flash, uint8_t *buf,
+                              unsigned int start, unsigned int len);
 static void satamv_chip_writeb(const struct flashctx *flash, uint8_t val,
                               chipaddr addr);
 static uint8_t satamv_chip_readb(const struct flashctx *flash,
                                 const chipaddr addr);
+
+static const struct spi_programmer spi_programmer_satamv = {
+       .type           = SPI_CONTROLLER_SATAMV,
+       .max_data_read  = MAX_DATA_READ_UNLIMITED,
+       .max_data_write = MAX_DATA_UNSPECIFIED,
+       .command        = satamv_spi_send_command,
+       .multicommand   = default_spi_send_multicommand,
+       .read           = default_spi_read,
+       .write_256      = satamv_spi_write_256,
+       .write_aai      = default_spi_write_aai,
+};
+
 static const struct par_programmer par_programmer_satamv = {
                .chip_readb             = satamv_chip_readb,
                .chip_readw             = fallback_chip_readw,
@@ -57,6 +89,44 @@ static const struct par_programmer par_programmer_satamv = {
                .chip_writen            = fallback_chip_writen,
 };
 
+static int init_94xx(struct pci_dev *dev)
+{
+       uintptr_t addr;
+       uint32_t tmp;
+
+       msg_pspew("Initializing 94xx\n");
+
+       addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_2);
+       if (!addr)
+               return 1;
+       msg_pspew("addr=0x%08" PRIXPTR "\n", addr);
+
+       mv_bar = rphysmap("Marvell 88SE94xx registers", addr, 0x40000);
+       if (mv_bar == ERROR_PTR)
+               return 1;
+       msg_pspew("mv_bar=%p\n", mv_bar);
+
+       /* Read some registers for fun.
+        * TODO: Remove once everything is working
+        */
+       tmp = pci_mmio_readl(mv_bar + EXPANSION_ROM_WINDOW0_REMAP);
+       msg_pspew("PCIe Expansion ROM Window Remap: 0x%04x\n", tmp);
+
+       tmp = pci_mmio_readl(mv_bar + SPI_FLASH_CONTROL);
+       msg_pspew("SPI Flash Control: 0x%08x\n", tmp);
+
+       tmp = pci_mmio_readl(mv_bar + SPI_FLASH_ADDRESS);
+       msg_pspew("SPI Flash Address: 0x%08x\n", tmp);
+
+       tmp = pci_mmio_readl(mv_bar + SPI_FLASH_READ_DATA);
+       msg_pspew("SPI Flash Read Data: 0x%08x\n", tmp);
+
+       /* Register SPI programmer */
+       register_spi_programmer(&spi_programmer_satamv);
+
+       return 0;
+}
+
 /*
  * Random notes:
  * FCE#                Flash Chip Enable
@@ -78,6 +148,7 @@ int satamv_init(void)
        struct pci_dev *dev = NULL;
        uintptr_t addr;
        uint32_t tmp;
+       uint16_t id;
 
        if (rget_io_perms())
                return 1;
@@ -87,6 +158,12 @@ int satamv_init(void)
        if (!dev)
                return 1;
 
+       id = dev->device_id;
+
+       /* If 9445, do separate init */
+       if (id == 0x9445)
+               return init_94xx(dev);
+
        addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0);
        if (!addr)
                return 1;
@@ -192,6 +269,80 @@ static uint8_t satamv_chip_readb(const struct flashctx 
*flash,
        return satamv_indirect_chip_readb(addr);
 }
 
+static int satamv_spi_send_command(struct flashctx *flash, unsigned int 
writecnt,
+               unsigned int readcnt,
+               const unsigned char *writearr,
+               unsigned char *readarr)
+{
+       uint8_t busy;
+       int i;
+
+       msg_pspew("%s:", __func__);
+       msg_pspew(" SPI Flash Control Start: 0x%04x", pci_mmio_readl(mv_bar + 
SPI_FLASH_CONTROL));
+       msg_pspew(" writecnt=%d, readcnt=%d\n", writecnt, readcnt);
+
+       for (i = 0; i < writecnt; i++)
+               msg_pspew("writearr[%d]=0x%x\n", i, writearr[i]);
+
+       do {
+               busy = pci_mmio_readl(mv_bar + SPI_FLASH_CONTROL);
+               msg_pspew("SPI Flash Control during busy wait (while loop 1): 
0x%04x\n", busy);
+               busy &= 0x1;
+       } while (busy);
+
+       if (readcnt > 4) {
+               msg_pinfo("%s called with unsupported readcnt %i.\n",
+                         __func__, readcnt);
+               return SPI_INVALID_LENGTH;
+       }
+
+       /* Write FFs to WRITE_DATA and READ_DATA */
+       pci_mmio_writel(0xffffffff, mv_bar + SPI_FLASH_WRITE_DATA);
+       pci_mmio_writel(0xffffffff, mv_bar + SPI_FLASH_READ_DATA);
+
+       switch (writecnt) {
+       case 1:
+               pci_mmio_writel((0x00000005 | (writearr[0]<<8) | (readcnt<<4)), 
mv_bar + SPI_FLASH_CONTROL);
+               break;
+       case 2:
+               break;
+       case 4:
+               break;
+       case 5:
+               break;
+       default:
+               msg_pinfo("%s called with unsupported writecnt %i.\n",
+                         __func__, writecnt);
+               return SPI_INVALID_LENGTH;
+       }
+
+       if (readcnt > 0) {
+               do {
+                       busy = pci_mmio_readl(mv_bar + SPI_FLASH_CONTROL);
+                       msg_pspew("SPI Flash Control during busy wait (while 
loop 2): 0x%04x\n", busy);
+                       busy &= 0x1;
+               } while (busy);
+
+               /* Read from SPI Flash */
+               pci_mmio_writel((0x00000005 | (readcnt<<4)), mv_bar + 
SPI_FLASH_CONTROL);
+               msg_pspew("SPI Return: 0x%04x\n", pci_mmio_readl(mv_bar + 
SPI_FLASH_READ_DATA));
+
+               for (i = 0; i < readcnt; i++)
+                       readarr[i] = pci_mmio_readl(mv_bar + 
SPI_FLASH_READ_DATA);
+       }
+
+       msg_pspew("SPI Flash Control End: 0x%04x\n", pci_mmio_readl(mv_bar + 
SPI_FLASH_CONTROL));
+
+       return 0;
+}
+
+static int satamv_spi_write_256(struct flashctx *flash, uint8_t *buf,
+               unsigned int start, unsigned int len)
+{
+       return spi_write_chunked(flash, buf, start, len,
+                       spi_write_256_chunksize);
+}
+
 #else
 #error PCI port I/O access is not supported on this architecture yet.
 #endif
-- 
1.9.2


_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to