]> git.sur5r.net Git - u-boot/blobdiff - drivers/spi/ich.c
spi: stm32_qspi: Align reg-names with kernel 4.12 RC1
[u-boot] / drivers / spi / ich.c
index d4888f5fa483b403daf99cdc25220922f6046797..03531a8c0c3f403ccf156f8782e743caf5f99990 100644 (file)
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 2011-12 The Chromium OS Authors.
  *
- * SPDX-License-Identifier:    GPL-2.0+
- *
  * This file is derived from the flashrom project.
  */
 
@@ -184,6 +183,19 @@ static inline void spi_use_in(struct spi_trans *trans, unsigned bytes)
        trans->bytesin -= bytes;
 }
 
+static void spi_lock_down(struct ich_spi_platdata *plat, void *sbase)
+{
+       if (plat->ich_version == ICHV_7) {
+               struct ich7_spi_regs *ich7_spi = sbase;
+
+               setbits_le16(&ich7_spi->spis, SPIS_LOCK);
+       } else if (plat->ich_version == ICHV_9) {
+               struct ich9_spi_regs *ich9_spi = sbase;
+
+               setbits_le16(&ich9_spi->hsfs, HSFS_FLOCKDN);
+       }
+}
+
 static bool spi_lock_status(struct ich_spi_platdata *plat, void *sbase)
 {
        int lock = 0;
@@ -338,6 +350,21 @@ static int ich_status_poll(struct ich_spi_priv *ctlr, u16 bitmask,
        return -ETIMEDOUT;
 }
 
+void ich_spi_config_opcode(struct udevice *dev)
+{
+       struct ich_spi_priv *ctlr = dev_get_priv(dev);
+
+       /*
+        * PREOP, OPTYPE, OPMENU1/OPMENU2 registers can be locked down
+        * to prevent accidental or intentional writes. Before they get
+        * locked down, these registers should be initialized properly.
+        */
+       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));
+}
+
 static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
                        const void *dout, void *din, unsigned long flags)
 {
@@ -453,8 +480,6 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
        }
 
        /* Preset control fields */
-       control = ich_readw(ctlr, ctlr->control);
-       control &= ~SSFC_RESERVED;
        control = SPIC_SCGO | ((opcode_index & 0x07) << 4);
 
        /* Issue atomic preop cycle if needed */
@@ -550,7 +575,8 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
        }
 
        /* Clear atomic preop now that xfer is done */
-       ich_writew(ctlr, 0, ctlr->preop);
+       if (!lock)
+               ich_writew(ctlr, 0, ctlr->preop);
 
        return 0;
 }
@@ -578,6 +604,12 @@ static int ich_spi_probe(struct udevice *dev)
                return ret;
        }
 
+       /* Lock down SPI controller settings if required */
+       if (plat->lockdown) {
+               ich_spi_config_opcode(dev);
+               spi_lock_down(plat, priv->base);
+       }
+
        priv->cur_speed = priv->max_speed;
 
        return 0;
@@ -585,16 +617,11 @@ static int ich_spi_probe(struct udevice *dev)
 
 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));
+       ich_spi_config_opcode(bus);
 
        return 0;
 }
@@ -653,6 +680,9 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
                        plat->ich_version = ICHV_9;
        }
 
+       plat->lockdown = fdtdec_get_bool(gd->fdt_blob, node,
+                                        "intel,spi-lock-down");
+
        return ret;
 }