This patch adds a remove function to the Intel ICH SPI driver, that will
be called upon U-Boot exit, directly before the OS (Linux) is started.
This function takes care of configuring the BIOS registers in the SPI
controller (similar to what a "standard" BIOS or coreboot does), so that
the Linux MTD device driver is able to correctly read/write to the SPI
NOR chip. Without this, the chip is not detected at all.

Signed-off-by: Stefan Roese <s...@denx.de>
Reviewed-by: Simon Glass <s...@chromium.org>
Cc: Bin Meng <bmeng...@gmail.com>
Cc: Jagan Teki <jt...@openedev.com>
---
v2:
- Added Simons RB line

 drivers/spi/ich.c | 18 ++++++++++++++++++
 drivers/spi/ich.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 65 insertions(+), 7 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index 893fe33b66..bf2e99b5cc 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -617,6 +617,22 @@ static int ich_spi_probe(struct udevice *dev)
        return 0;
 }
 
+static int ich_spi_remove(struct udevice *bus)
+{
+       struct ich_spi_priv *ctlr = dev_get_priv(bus);
+
+       /*
+        * Configure SPI controller so that the Linux MTD driver can fully
+        * access the SPI NOR chip
+        */
+       ich_writew(ctlr, SPI_OPPREFIX, ctlr->preop);
+       ich_writew(ctlr, SPI_OPTYPE, ctlr->optype);
+       ich_writel(ctlr, SPI_OPMENU_LOWER, ctlr->opmenu);
+       ich_writel(ctlr, SPI_OPMENU_UPPER, ctlr->opmenu + sizeof(u32));
+
+       return 0;
+}
+
 static int ich_spi_set_speed(struct udevice *bus, uint speed)
 {
        struct ich_spi_priv *priv = dev_get_priv(bus);
@@ -700,4 +716,6 @@ U_BOOT_DRIVER(ich_spi) = {
        .priv_auto_alloc_size = sizeof(struct ich_spi_priv),
        .child_pre_probe = ich_spi_child_pre_probe,
        .probe  = ich_spi_probe,
+       .remove = ich_spi_remove,
+       .flags  = DM_FLAG_OS_PREPARE,
 };
diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
index bd0a820809..dcb8a9048f 100644
--- a/drivers/spi/ich.h
+++ b/drivers/spi/ich.h
@@ -102,13 +102,6 @@ enum {
 };
 
 enum {
-       SPI_OPCODE_TYPE_READ_NO_ADDRESS =       0,
-       SPI_OPCODE_TYPE_WRITE_NO_ADDRESS =      1,
-       SPI_OPCODE_TYPE_READ_WITH_ADDRESS =     2,
-       SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS =    3
-};
-
-enum {
        ICH_MAX_CMD_LEN         = 5,
 };
 
@@ -124,8 +117,55 @@ struct spi_trans {
        uint32_t offset;
 };
 
+#define SPI_OPCODE_WRSR                0x01
+#define SPI_OPCODE_PAGE_PROGRAM        0x02
+#define SPI_OPCODE_READ                0x03
+#define SPI_OPCODE_WRDIS       0x04
+#define SPI_OPCODE_RDSR                0x05
 #define SPI_OPCODE_WREN                0x06
 #define SPI_OPCODE_FAST_READ   0x0b
+#define SPI_OPCODE_ERASE_SECT  0x20
+#define SPI_OPCODE_READ_ID     0x9f
+#define SPI_OPCODE_ERASE_BLOCK 0xd8
+
+#define SPI_OPCODE_TYPE_READ_NO_ADDRESS                0
+#define SPI_OPCODE_TYPE_WRITE_NO_ADDRESS       1
+#define SPI_OPCODE_TYPE_READ_WITH_ADDRESS      2
+#define SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS     3
+
+#define SPI_OPMENU_0   SPI_OPCODE_WRSR
+#define SPI_OPTYPE_0   SPI_OPCODE_TYPE_WRITE_NO_ADDRESS
+
+#define SPI_OPMENU_1   SPI_OPCODE_PAGE_PROGRAM
+#define SPI_OPTYPE_1   SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS
+
+#define SPI_OPMENU_2   SPI_OPCODE_READ
+#define SPI_OPTYPE_2   SPI_OPCODE_TYPE_READ_WITH_ADDRESS
+
+#define SPI_OPMENU_3   SPI_OPCODE_RDSR
+#define SPI_OPTYPE_3   SPI_OPCODE_TYPE_READ_NO_ADDRESS
+
+#define SPI_OPMENU_4   SPI_OPCODE_ERASE_SECT
+#define SPI_OPTYPE_4   SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS
+
+#define SPI_OPMENU_5   SPI_OPCODE_READ_ID
+#define SPI_OPTYPE_5   SPI_OPCODE_TYPE_READ_NO_ADDRESS
+
+#define SPI_OPMENU_6   SPI_OPCODE_ERASE_BLOCK
+#define SPI_OPTYPE_6   SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS
+
+#define SPI_OPMENU_7   SPI_OPCODE_FAST_READ
+#define SPI_OPTYPE_7   SPI_OPCODE_TYPE_READ_WITH_ADDRESS
+
+#define SPI_OPPREFIX   ((SPI_OPCODE_WREN << 8) | SPI_OPCODE_WREN)
+#define SPI_OPTYPE     ((SPI_OPTYPE_7 << 14) | (SPI_OPTYPE_6 << 12) | \
+                        (SPI_OPTYPE_5 << 10) | (SPI_OPTYPE_4 <<  8) | \
+                        (SPI_OPTYPE_3 <<  6) | (SPI_OPTYPE_2 <<  4) | \
+                        (SPI_OPTYPE_1 <<  2) | (SPI_OPTYPE_0 <<  0))
+#define SPI_OPMENU_UPPER ((SPI_OPMENU_7 << 24) | (SPI_OPMENU_6 << 16) | \
+                         (SPI_OPMENU_5 <<  8) | (SPI_OPMENU_4 <<  0))
+#define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \
+                         (SPI_OPMENU_1 <<  8) | (SPI_OPMENU_0 <<  0))
 
 enum ich_version {
        ICHV_7,
-- 
2.12.2

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to