]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/spi/spi-bcm-qspi.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / drivers / spi / spi-bcm-qspi.c
index d7843fd8c610427d1da58a689c115025084eced2..b19722ba908c1be3855e42d21b25f2e6fb38eae8 100644 (file)
@@ -89,7 +89,7 @@
 #define BSPI_BPP_MODE_SELECT_MASK              BIT(8)
 #define BSPI_BPP_ADDR_SELECT_MASK              BIT(16)
 
-#define BSPI_READ_LENGTH                       256
+#define BSPI_READ_LENGTH                       512
 
 /* MSPI register offsets */
 #define MSPI_SPCR0_LSB                         0x000
@@ -192,9 +192,11 @@ struct bcm_qspi_dev_id {
        void *dev;
 };
 
+
 struct qspi_trans {
        struct spi_transfer *trans;
        int byte;
+       bool mspi_last_trans;
 };
 
 struct bcm_qspi {
@@ -616,6 +618,16 @@ static int bcm_qspi_setup(struct spi_device *spi)
        return 0;
 }
 
+static bool bcm_qspi_mspi_transfer_is_last(struct bcm_qspi *qspi,
+                                          struct qspi_trans *qt)
+{
+       if (qt->mspi_last_trans &&
+           spi_transfer_is_last(qspi->master, qt->trans))
+               return true;
+       else
+               return false;
+}
+
 static int update_qspi_trans_byte_count(struct bcm_qspi *qspi,
                                        struct qspi_trans *qt, int flags)
 {
@@ -629,7 +641,6 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi,
 
        if (qt->byte >= qt->trans->len) {
                /* we're at the end of the spi_transfer */
-
                /* in TX mode, need to pause for a delay or CS change */
                if (qt->trans->delay_usecs &&
                    (flags & TRANS_STATUS_BREAK_DELAY))
@@ -641,7 +652,7 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi,
                        goto done;
 
                dev_dbg(&qspi->pdev->dev, "advance msg exit\n");
-               if (spi_transfer_is_last(qspi->master, qt->trans))
+               if (bcm_qspi_mspi_transfer_is_last(qspi, qt))
                        ret = TRANS_STATUS_BREAK_EOM;
                else
                        ret = TRANS_STATUS_BREAK_NO_BYTES;
@@ -813,7 +824,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
                                    struct spi_flash_read_message *msg)
 {
        struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
-       u32 addr = 0, len, len_words;
+       u32 addr = 0, len, rdlen, len_words;
        int ret = 0;
        unsigned long timeo = msecs_to_jiffies(100);
        struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;
@@ -826,7 +837,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
        bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0);
 
        /*
-        * when using flex mode mode we need to send
+        * when using flex mode we need to send
         * the upper address byte to bspi
         */
        if (bcm_qspi_bspi_ver_three(qspi) == false) {
@@ -840,48 +851,127 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
        else
                addr = msg->from & 0x00ffffff;
 
-       /* set BSPI RAF buffer max read length */
-       len = msg->len;
-       if (len > BSPI_READ_LENGTH)
-               len = BSPI_READ_LENGTH;
-
        if (bcm_qspi_bspi_ver_three(qspi) == true)
                addr = (addr + 0xc00000) & 0xffffff;
 
-       reinit_completion(&qspi->bspi_done);
-       bcm_qspi_enable_bspi(qspi);
-       len_words = (len + 3) >> 2;
-       qspi->bspi_rf_msg = msg;
-       qspi->bspi_rf_msg_status = 0;
+       /*
+        * read into the entire buffer by breaking the reads
+        * into RAF buffer read lengths
+        */
+       len = msg->len;
        qspi->bspi_rf_msg_idx = 0;
-       qspi->bspi_rf_msg_len = len;
-       dev_dbg(&qspi->pdev->dev, "bspi xfr addr 0x%x len 0x%x", addr, len);
 
-       bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr);
-       bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words);
-       bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0);
+       do {
+               if (len > BSPI_READ_LENGTH)
+                       rdlen = BSPI_READ_LENGTH;
+               else
+                       rdlen = len;
+
+               reinit_completion(&qspi->bspi_done);
+               bcm_qspi_enable_bspi(qspi);
+               len_words = (rdlen + 3) >> 2;
+               qspi->bspi_rf_msg = msg;
+               qspi->bspi_rf_msg_status = 0;
+               qspi->bspi_rf_msg_len = rdlen;
+               dev_dbg(&qspi->pdev->dev,
+                       "bspi xfr addr 0x%x len 0x%x", addr, rdlen);
+               bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr);
+               bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words);
+               bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0);
+               if (qspi->soc_intc) {
+                       /*
+                        * clear soc MSPI and BSPI interrupts and enable
+                        * BSPI interrupts.
+                        */
+                       soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_BSPI_DONE);
+                       soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, true);
+               }
 
-       if (qspi->soc_intc) {
-               /*
-                * clear soc MSPI and BSPI interrupts and enable
-                * BSPI interrupts.
-                */
-               soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_BSPI_DONE);
-               soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, true);
+               /* Must flush previous writes before starting BSPI operation */
+               mb();
+               bcm_qspi_bspi_lr_start(qspi);
+               if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) {
+                       dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n");
+                       ret = -ETIMEDOUT;
+                       break;
+               }
+
+               /* set msg return length */
+               msg->retlen += rdlen;
+               addr += rdlen;
+               len -= rdlen;
+       } while (len);
+
+       return ret;
+}
+
+static int bcm_qspi_transfer_one(struct spi_master *master,
+                                struct spi_device *spi,
+                                struct spi_transfer *trans)
+{
+       struct bcm_qspi *qspi = spi_master_get_devdata(master);
+       int slots;
+       unsigned long timeo = msecs_to_jiffies(100);
+
+       bcm_qspi_chip_select(qspi, spi->chip_select);
+       qspi->trans_pos.trans = trans;
+       qspi->trans_pos.byte = 0;
+
+       while (qspi->trans_pos.byte < trans->len) {
+               reinit_completion(&qspi->mspi_done);
+
+               slots = write_to_hw(qspi, spi);
+               if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) {
+                       dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n");
+                       return -ETIMEDOUT;
+               }
+
+               read_from_hw(qspi, slots);
        }
 
-       /* Must flush previous writes before starting BSPI operation */
-       mb();
+       return 0;
+}
 
-       bcm_qspi_bspi_lr_start(qspi);
-       if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) {
-               dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n");
-               ret = -ETIMEDOUT;
-       } else {
-               /* set the return length for the caller */
-               msg->retlen = len;
+static int bcm_qspi_mspi_flash_read(struct spi_device *spi,
+                                   struct spi_flash_read_message *msg)
+{
+       struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
+       struct spi_transfer t[2];
+       u8 cmd[6];
+       int ret;
+
+       memset(cmd, 0, sizeof(cmd));
+       memset(t, 0, sizeof(t));
+
+       /* tx */
+       /* opcode is in cmd[0] */
+       cmd[0] = msg->read_opcode;
+       cmd[1] = msg->from >> (msg->addr_width * 8 -  8);
+       cmd[2] = msg->from >> (msg->addr_width * 8 - 16);
+       cmd[3] = msg->from >> (msg->addr_width * 8 - 24);
+       cmd[4] = msg->from >> (msg->addr_width * 8 - 32);
+       t[0].tx_buf = cmd;
+       t[0].len = msg->addr_width + msg->dummy_bytes + 1;
+       t[0].bits_per_word = spi->bits_per_word;
+       t[0].tx_nbits = msg->opcode_nbits;
+       /* lets mspi know that this is not last transfer */
+       qspi->trans_pos.mspi_last_trans = false;
+       ret = bcm_qspi_transfer_one(spi->master, spi, &t[0]);
+
+       /* rx */
+       qspi->trans_pos.mspi_last_trans = true;
+       if (!ret) {
+               /* rx */
+               t[1].rx_buf = msg->buf;
+               t[1].len = msg->len;
+               t[1].rx_nbits =  msg->data_nbits;
+               t[1].bits_per_word = spi->bits_per_word;
+               ret = bcm_qspi_transfer_one(spi->master, spi, &t[1]);
        }
 
+       if (!ret)
+               msg->retlen = msg->len;
+
        return ret;
 }
 
@@ -918,8 +1008,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
                mspi_read = true;
 
        if (mspi_read)
-               /* this will make the m25p80 read to fallback to mspi read */
-               return -EAGAIN;
+               return bcm_qspi_mspi_flash_read(spi, msg);
 
        io_width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
        addrlen = msg->addr_width;
@@ -931,33 +1020,6 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
        return ret;
 }
 
-static int bcm_qspi_transfer_one(struct spi_master *master,
-                                struct spi_device *spi,
-                                struct spi_transfer *trans)
-{
-       struct bcm_qspi *qspi = spi_master_get_devdata(master);
-       int slots;
-       unsigned long timeo = msecs_to_jiffies(100);
-
-       bcm_qspi_chip_select(qspi, spi->chip_select);
-       qspi->trans_pos.trans = trans;
-       qspi->trans_pos.byte = 0;
-
-       while (qspi->trans_pos.byte < trans->len) {
-               reinit_completion(&qspi->mspi_done);
-
-               slots = write_to_hw(qspi, spi);
-               if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) {
-                       dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n");
-                       return -ETIMEDOUT;
-               }
-
-               read_from_hw(qspi, slots);
-       }
-
-       return 0;
-}
-
 static void bcm_qspi_cleanup(struct spi_device *spi)
 {
        struct bcm_qspi_parms *xp = spi_get_ctldata(spi);
@@ -1187,6 +1249,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
        qspi->pdev = pdev;
        qspi->trans_pos.trans = NULL;
        qspi->trans_pos.byte = 0;
+       qspi->trans_pos.mspi_last_trans = true;
        qspi->master = master;
 
        master->bus_num = -1;
@@ -1345,7 +1408,6 @@ int bcm_qspi_remove(struct platform_device *pdev)
 {
        struct bcm_qspi *qspi = platform_get_drvdata(pdev);
 
-       platform_set_drvdata(pdev, NULL);
        bcm_qspi_hw_uninit(qspi);
        clk_disable_unprepare(qspi->clk);
        kfree(qspi->dev_ids);