diff mbox

[RFC] spi: Using Trigger number to transmit/receive data

Message ID 1394699364-5669-2-git-send-email-cm-hiep@jinso.co.jp (mailing list archive)
State RFC
Headers show

Commit Message

Cao Minh Hiep March 13, 2014, 8:29 a.m. UTC
From: Hiep Cao Minh <cm-hiep@jinso.co.jp>

In order to transmit and receive data when have 32 bytes of data that
ready has prepared on Transmit/Receive Buffer to transmit or receive.
Instead transmits/receives a byte data using Transmit/Receive Buffer
Data Triggering Number will improve the speed of transfer data.

Signed-off-by: Hiep Cao Minh <cm-hiep@jinso.co.jp>
---
 drivers/spi/spi-rspi.c |  144 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 124 insertions(+), 20 deletions(-)

Comments

Geert Uytterhoeven March 13, 2014, 9:23 a.m. UTC | #1
On Thu, Mar 13, 2014 at 9:29 AM, Cao Minh Hiep <cm-hiep@jinso.co.jp> wrote:
> In order to transmit and receive data when have 32 bytes of data that
> ready has prepared on Transmit/Receive Buffer to transmit or receive.
> Instead transmits/receives a byte data using Transmit/Receive Buffer
> Data Triggering Number will improve the speed of transfer data.

Thanks for your patch, this looks like a valuable improvement!

Unfortunately your patch doesn't apply against spi/for-next anymore, as
the driver has changed a lot lately, due to the addition of RZ/A1H and
Quad/Dual support.

> +static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg)
> +{
> +       u8 data;
> +
> +       data = rspi_read8(rspi, reg);
> +       data &= ~mask;
> +       data |= (val & mask);

I think this "& mask" is superfluous.

> +       rspi_write8(rspi, data, reg);
> +}

> +static int qspi_set_send_trigger(struct rspi_data *rspi, int remain)
> +{
> +       int n;
> +
> +       n = min(remain, QSPI_BUFFER_SIZE);
> +
> +       if (remain >= QSPI_BUFFER_SIZE) {
> +               /* sets triggering number to 32 bytes */

"0 bytes"? (comment copied from qspi_set_receive_trigger())

> +               qspi_update(rspi, SPBFCR_TXTRG_MASK,
> +                            SPBFCR_TXTRG_0B, QSPI_SPBFCR);
> +       } else {
> +               /* sets triggering number to 1 byte */

"31 bytes"?

> +               qspi_update(rspi, SPBFCR_TXTRG_MASK,
> +                            SPBFCR_TXTRG_31B, QSPI_SPBFCR);
> +       }

> @@ -389,9 +443,10 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
>  {
>         int remain = t->len;
>         const u8 *data = t->tx_buf;
> +       int i, n;
>
>         rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
> -       rspi_write8(rspi, 0x00, QSPI_SPBFCR);
> +       rspi_write8(rspi, DUMMY_DATA, QSPI_SPBFCR);

I think this should stay "0x00", as it's not dummy data written to the
transmit data register.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kuninori Morimoto March 13, 2014, 9:27 a.m. UTC | #2
Hi Hiep

> In order to transmit and receive data when have 32 bytes of data that
> ready has prepared on Transmit/Receive Buffer to transmit or receive.
> Instead transmits/receives a byte data using Transmit/Receive Buffer
> Data Triggering Number will improve the speed of transfer data.
> 
> Signed-off-by: Hiep Cao Minh <cm-hiep@jinso.co.jp>
> ---
(snip)
> +static int qspi_set_send_trigger(struct rspi_data *rspi, int remain)
> +{
> +	int n;
> +
> +	n = min(remain, QSPI_BUFFER_SIZE);
> +
> +	if (remain >= QSPI_BUFFER_SIZE) {
> +		/* sets triggering number to 32 bytes */
> +		qspi_update(rspi, SPBFCR_TXTRG_MASK,
> +			     SPBFCR_TXTRG_0B, QSPI_SPBFCR);
> +	} else {
> +		/* sets triggering number to 1 byte */
> +		qspi_update(rspi, SPBFCR_TXTRG_MASK,
> +			     SPBFCR_TXTRG_31B, QSPI_SPBFCR);
> +	}
> +
> +	return n;
> +}
(snip)
> +		n = qspi_set_send_trigger(rspi, remain);
> +		if (n >= QSPI_BUFFER_SIZE) {
> +			for (i = 0; i < n; i++)
> +				rspi_write8(rspi, *data++, RSPI_SPDR);
> +			if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
> +						    SPCR_SPRIE) < 0) {
> +				dev_err(&rspi->master->dev,
> +					"%s: receive timeout\n", __func__);
> +				return -ETIMEDOUT;
> +			}
> +			for (i = 0; i < n; i++)
> +				rspi_read8(rspi, RSPI_SPDR);
> +		} else {
> +			for (i = 0; i < n; i++) {
> +				if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF,
> +							    SPCR_SPTIE) < 0) {
> +					dev_err(&rspi->master->dev,
> +					   "%s: tx empty timeout\n", __func__);
> +				return -ETIMEDOUT;
> +				}
> +				rspi_write8(rspi, *data++, RSPI_SPDR);
> +
> +				if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
> +							    SPCR_SPRIE) < 0) {
> +					dev_err(&rspi->master->dev,
> +					   "%s: receive timeout\n", __func__);
> +				return -ETIMEDOUT;
> +				}
> +				rspi_read8(rspi, RSPI_SPDR);
> +			}

I guess, this "qspi_set_send_trigger()" is mode "settings",
and, "transfer" is done here.

I think "setting" and "tranfer" in 1 function is readable.
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Cao Minh Hiep March 17, 2014, 1:11 a.m. UTC | #3
On 03/13/2014 06:23 PM, Geert Uytterhoeven wrote:
> On Thu, Mar 13, 2014 at 9:29 AM, Cao Minh Hiep <cm-hiep@jinso.co.jp> wrote:
>> In order to transmit and receive data when have 32 bytes of data that
>> ready has prepared on Transmit/Receive Buffer to transmit or receive.
>> Instead transmits/receives a byte data using Transmit/Receive Buffer
>> Data Triggering Number will improve the speed of transfer data.
> Thanks for your patch, this looks like a valuable improvement!
>
> Unfortunately your patch doesn't apply against spi/for-next anymore, as
> the driver has changed a lot lately, due to the addition of RZ/A1H and
> Quad/Dual support.
>
Thanks, Do you mean this patch did not need for next and I don't mind 
about it?
>> +static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg)
>> +{
>> +       u8 data;
>> +
>> +       data = rspi_read8(rspi, reg);
>> +       data &= ~mask;
>> +       data |= (val & mask);
> I think this "& mask" is superfluous.
thanks, I modified it.
>> +       rspi_write8(rspi, data, reg);
>> +}
>> +static int qspi_set_send_trigger(struct rspi_data *rspi, int remain)
>> +{
>> +       int n;
>> +
>> +       n = min(remain, QSPI_BUFFER_SIZE);
>> +
>> +       if (remain >= QSPI_BUFFER_SIZE) {
>> +               /* sets triggering number to 32 bytes */
> "0 bytes"? (comment copied from qspi_set_receive_trigger())
>
>> +               qspi_update(rspi, SPBFCR_TXTRG_MASK,
>> +                            SPBFCR_TXTRG_0B, QSPI_SPBFCR);
>> +       } else {
>> +               /* sets triggering number to 1 byte */
> "31 bytes"?
thanks,
>> +               qspi_update(rspi, SPBFCR_TXTRG_MASK,
>> +                            SPBFCR_TXTRG_31B, QSPI_SPBFCR);
>> +       }
>> @@ -389,9 +443,10 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
>>   {
>>          int remain = t->len;
>>          const u8 *data = t->tx_buf;
>> +       int i, n;
>>
>>          rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
>> -       rspi_write8(rspi, 0x00, QSPI_SPBFCR);
>> +       rspi_write8(rspi, DUMMY_DATA, QSPI_SPBFCR);
> I think this should stay "0x00", as it's not dummy data written to the
> transmit data register.
Thanks,
> Gr{oetje,eeting}s,
>
>                          Geert
>
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
>
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                  -- Linus Torvalds
>
>

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Cao Minh Hiep March 17, 2014, 1:15 a.m. UTC | #4
Hi Morimoto

On 03/13/2014 06:27 PM, Kuninori Morimoto wrote:
> Hi Hiep
>
>> In order to transmit and receive data when have 32 bytes of data that
>> ready has prepared on Transmit/Receive Buffer to transmit or receive.
>> Instead transmits/receives a byte data using Transmit/Receive Buffer
>> Data Triggering Number will improve the speed of transfer data.
>>
>> Signed-off-by: Hiep Cao Minh <cm-hiep@jinso.co.jp>
>> ---
> (snip)
>> +static int qspi_set_send_trigger(struct rspi_data *rspi, int remain)
>> +{
>> +	int n;
>> +
>> +	n = min(remain, QSPI_BUFFER_SIZE);
>> +
>> +	if (remain >= QSPI_BUFFER_SIZE) {
>> +		/* sets triggering number to 32 bytes */
>> +		qspi_update(rspi, SPBFCR_TXTRG_MASK,
>> +			     SPBFCR_TXTRG_0B, QSPI_SPBFCR);
>> +	} else {
>> +		/* sets triggering number to 1 byte */
>> +		qspi_update(rspi, SPBFCR_TXTRG_MASK,
>> +			     SPBFCR_TXTRG_31B, QSPI_SPBFCR);
>> +	}
>> +
>> +	return n;
>> +}
> (snip)
>> +		n = qspi_set_send_trigger(rspi, remain);
>> +		if (n >= QSPI_BUFFER_SIZE) {
>> +			for (i = 0; i < n; i++)
>> +				rspi_write8(rspi, *data++, RSPI_SPDR);
>> +			if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
>> +						    SPCR_SPRIE) < 0) {
>> +				dev_err(&rspi->master->dev,
>> +					"%s: receive timeout\n", __func__);
>> +				return -ETIMEDOUT;
>> +			}
>> +			for (i = 0; i < n; i++)
>> +				rspi_read8(rspi, RSPI_SPDR);
>> +		} else {
>> +			for (i = 0; i < n; i++) {
>> +				if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF,
>> +							    SPCR_SPTIE) < 0) {
>> +					dev_err(&rspi->master->dev,
>> +					   "%s: tx empty timeout\n", __func__);
>> +				return -ETIMEDOUT;
>> +				}
>> +				rspi_write8(rspi, *data++, RSPI_SPDR);
>> +
>> +				if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
>> +							    SPCR_SPRIE) < 0) {
>> +					dev_err(&rspi->master->dev,
>> +					   "%s: receive timeout\n", __func__);
>> +				return -ETIMEDOUT;
>> +				}
>> +				rspi_read8(rspi, RSPI_SPDR);
>> +			}
> I guess, this "qspi_set_send_trigger()" is mode "settings",
> and, "transfer" is done here.
>
> I think "setting" and "tranfer" in 1 function is readable.
>
Thanks for your comments, I will do so.
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Geert Uytterhoeven March 17, 2014, 7:54 a.m. UTC | #5
Hi Hiep,

On Mon, Mar 17, 2014 at 2:11 AM, ?????????? <cm-hiep@jinso.co.jp> wrote:
> On 03/13/2014 06:23 PM, Geert Uytterhoeven wrote:
>> On Thu, Mar 13, 2014 at 9:29 AM, Cao Minh Hiep <cm-hiep@jinso.co.jp>
>> wrote:
>>> In order to transmit and receive data when have 32 bytes of data that
>>> ready has prepared on Transmit/Receive Buffer to transmit or receive.
>>> Instead transmits/receives a byte data using Transmit/Receive Buffer
>>> Data Triggering Number will improve the speed of transfer data.
>>
>> Thanks for your patch, this looks like a valuable improvement!
>>
>> Unfortunately your patch doesn't apply against spi/for-next anymore, as
>> the driver has changed a lot lately, due to the addition of RZ/A1H and
>> Quad/Dual support.
>>
> Thanks, Do you mean this patch did not need for next and I don't mind about
> it?

It means you will have to rework your patch to apply on top of
https://git.kernel.org/cgit/linux/kernel/git/broonie/spi.git/tree/drivers/spi?h=for-next
before the SPI maintainer can accept it.

Thanks!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Cao Minh Hiep March 17, 2014, 12:01 p.m. UTC | #6
Hi Geert

On 03/17/2014 04:54 PM, Geert Uytterhoeven wrote:
> Hi Hiep,
>
> On Mon, Mar 17, 2014 at 2:11 AM, ?????????? <cm-hiep@jinso.co.jp> wrote:
>> On 03/13/2014 06:23 PM, Geert Uytterhoeven wrote:
>>> On Thu, Mar 13, 2014 at 9:29 AM, Cao Minh Hiep <cm-hiep@jinso.co.jp>
>>> wrote:
>>>> In order to transmit and receive data when have 32 bytes of data that
>>>> ready has prepared on Transmit/Receive Buffer to transmit or receive.
>>>> Instead transmits/receives a byte data using Transmit/Receive Buffer
>>>> Data Triggering Number will improve the speed of transfer data.
>>> Thanks for your patch, this looks like a valuable improvement!
>>>
>>> Unfortunately your patch doesn't apply against spi/for-next anymore, as
>>> the driver has changed a lot lately, due to the addition of RZ/A1H and
>>> Quad/Dual support.
>>>
>> Thanks, Do you mean this patch did not need for next and I don't mind about
>> it?
> It means you will have to rework your patch to apply on top of
> https://git.kernel.org/cgit/linux/kernel/git/broonie/spi.git/tree/drivers/spi?h=for-next
> before the SPI maintainer can accept it.
Thanks, I understood, I will rework my patch and report to your later.

Cao Minh Hiep.

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Geert Uytterhoeven March 17, 2014, 7:48 p.m. UTC | #7
Hi Hiep,

On Mon, Mar 17, 2014 at 1:01 PM, ?????????? <cm-hiep@jinso.co.jp> wrote:
> On 03/17/2014 04:54 PM, Geert Uytterhoeven wrote:
>> On Mon, Mar 17, 2014 at 2:11 AM, ?????????? <cm-hiep@jinso.co.jp> wrote:
>>> On 03/13/2014 06:23 PM, Geert Uytterhoeven wrote:
>>>> On Thu, Mar 13, 2014 at 9:29 AM, Cao Minh Hiep <cm-hiep@jinso.co.jp>
>>>> wrote:
>>>>> In order to transmit and receive data when have 32 bytes of data that
>>>>> ready has prepared on Transmit/Receive Buffer to transmit or receive.
>>>>> Instead transmits/receives a byte data using Transmit/Receive Buffer
>>>>> Data Triggering Number will improve the speed of transfer data.
>>>>
>>>> Thanks for your patch, this looks like a valuable improvement!
>>>>
>>>> Unfortunately your patch doesn't apply against spi/for-next anymore, as
>>>> the driver has changed a lot lately, due to the addition of RZ/A1H and
>>>> Quad/Dual support.
>>>>
>>> Thanks, Do you mean this patch did not need for next and I don't mind
>>> about
>>> it?
>>
>> It means you will have to rework your patch to apply on top of
>>
>> https://git.kernel.org/cgit/linux/kernel/git/broonie/spi.git/tree/drivers/spi?h=for-next
>> before the SPI maintainer can accept it.
>
> Thanks, I understood, I will rework my patch and report to your later.

I gave your patch a try on a v3.14-rc5 kernel on r8a7791/Koelsch,
and it increased Single SPI read transfer speed from ca. 1 Mbps to 11 Mbps.
So I'm looking forward to an updated version.

Thanks!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown March 17, 2014, 8:32 p.m. UTC | #8
On Mon, Mar 17, 2014 at 08:48:43PM +0100, Geert Uytterhoeven wrote:

> I gave your patch a try on a v3.14-rc5 kernel on r8a7791/Koelsch,
> and it increased Single SPI read transfer speed from ca. 1 Mbps to 11 Mbps.
> So I'm looking forward to an updated version.

Nice!
Cao Minh Hiep March 19, 2014, 12:50 a.m. UTC | #9
Hi Geert

On 03/18/2014 04:48 AM, Geert Uytterhoeven wrote:
> Hi Hiep,
>
> On Mon, Mar 17, 2014 at 1:01 PM, ?????????? <cm-hiep@jinso.co.jp> wrote:
>> On 03/17/2014 04:54 PM, Geert Uytterhoeven wrote:
>>> On Mon, Mar 17, 2014 at 2:11 AM, ?????????? <cm-hiep@jinso.co.jp> wrote:
>>>> On 03/13/2014 06:23 PM, Geert Uytterhoeven wrote:
>>>>> On Thu, Mar 13, 2014 at 9:29 AM, Cao Minh Hiep <cm-hiep@jinso.co.jp>
>>>>> wrote:
>>>>>> In order to transmit and receive data when have 32 bytes of data that
>>>>>> ready has prepared on Transmit/Receive Buffer to transmit or receive.
>>>>>> Instead transmits/receives a byte data using Transmit/Receive Buffer
>>>>>> Data Triggering Number will improve the speed of transfer data.
>>>>> Thanks for your patch, this looks like a valuable improvement!
>>>>>
>>>>> Unfortunately your patch doesn't apply against spi/for-next anymore, as
>>>>> the driver has changed a lot lately, due to the addition of RZ/A1H and
>>>>> Quad/Dual support.
>>>>>
>>>> Thanks, Do you mean this patch did not need for next and I don't mind
>>>> about
>>>> it?
>>> It means you will have to rework your patch to apply on top of
>>>
>>> https://git.kernel.org/cgit/linux/kernel/git/broonie/spi.git/tree/drivers/spi?h=for-next
>>> before the SPI maintainer can accept it.
>> Thanks, I understood, I will rework my patch and report to your later.
> I gave your patch a try on a v3.14-rc5 kernel on r8a7791/Koelsch,
> and it increased Single SPI read transfer speed from ca. 1 Mbps to 11 Mbps.
> So I'm looking forward to an updated version.
Thanks, I am modifying my patch and will send it to you as soon as possible.

Hiep

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kuninori Morimoto March 19, 2014, 1:17 a.m. UTC | #10
Hi Geert, Hiep

> > +static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg)
> > +{
> > +       u8 data;
> > +
> > +       data = rspi_read8(rspi, reg);
> > +       data &= ~mask;
> > +       data |= (val & mask);
> 
> I think this "& mask" is superfluous.

This "& mask" protects data from un-anticipative overwrite IMO.
Other driver is using same style.
ex) snd_soc_update_bits()

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 28987d9..772a942 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -174,6 +174,12 @@ 
 #define SPBFCR_RXRST		0x40	/* Receive Buffer Data Reset (qspi only) */
 #define SPBFCR_TXTRG_MASK	0x30	/* Transmit Buffer Data Triggering Number */
 #define SPBFCR_RXTRG_MASK	0x07	/* Receive Buffer Data Triggering Number */
+#define SPBFCR_TXTRG_31B	0x00	/* QSPI only */
+#define SPBFCR_TXTRG_0B		0x30	/* QSPI only */
+#define SPBFCR_RXTRG_1B		0x00	/* QSPI only */
+#define SPBFCR_RXTRG_32B	0x07	/* QSPI only */
+
+#define QSPI_BUFFER_SIZE        32
 
 #define DUMMY_DATA		0x00
 
@@ -224,6 +230,16 @@  static u16 rspi_read16(const struct rspi_data *rspi, u16 offset)
 	return ioread16(rspi->addr + offset);
 }
 
+static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg)
+{
+	u8 data;
+
+	data = rspi_read8(rspi, reg);
+	data &= ~mask;
+	data |= (val & mask);
+	rspi_write8(rspi, data, reg);
+}
+
 /* optional functions */
 struct spi_ops {
 	int (*set_config_register)(const struct rspi_data *rspi,
@@ -358,6 +374,44 @@  static void rspi_negate_ssl(const struct rspi_data *rspi)
 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
 }
 
+static int qspi_set_send_trigger(struct rspi_data *rspi, int remain)
+{
+	int n;
+
+	n = min(remain, QSPI_BUFFER_SIZE);
+
+	if (remain >= QSPI_BUFFER_SIZE) {
+		/* sets triggering number to 32 bytes */
+		qspi_update(rspi, SPBFCR_TXTRG_MASK,
+			     SPBFCR_TXTRG_0B, QSPI_SPBFCR);
+	} else {
+		/* sets triggering number to 1 byte */
+		qspi_update(rspi, SPBFCR_TXTRG_MASK,
+			     SPBFCR_TXTRG_31B, QSPI_SPBFCR);
+	}
+
+	return n;
+}
+
+static int qspi_set_receive_trigger(struct rspi_data *rspi, int remain)
+{
+	int n;
+
+	n = min(remain, QSPI_BUFFER_SIZE);
+
+	if (remain >= QSPI_BUFFER_SIZE) {
+		/* sets triggering number to 32 bytes */
+		qspi_update(rspi, SPBFCR_RXTRG_MASK,
+			     SPBFCR_RXTRG_32B, QSPI_SPBFCR);
+	} else {
+		/* sets triggering number to 1 byte */
+		qspi_update(rspi, SPBFCR_RXTRG_MASK,
+			     SPBFCR_RXTRG_1B, QSPI_SPBFCR);
+	}
+
+	return n;
+}
+
 static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
 			 struct spi_transfer *t)
 {
@@ -389,9 +443,10 @@  static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
 {
 	int remain = t->len;
 	const u8 *data = t->tx_buf;
+	int i, n;
 
 	rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
-	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
+	rspi_write8(rspi, DUMMY_DATA, QSPI_SPBFCR);
 
 	while (remain > 0) {
 
@@ -400,16 +455,38 @@  static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
 				"%s: tx empty timeout\n", __func__);
 			return -ETIMEDOUT;
 		}
-		rspi_write8(rspi, *data++, RSPI_SPDR);
-
-		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
-			dev_err(&rspi->master->dev,
-				"%s: receive timeout\n", __func__);
-			return -ETIMEDOUT;
+		n = qspi_set_send_trigger(rspi, remain);
+		if (n >= QSPI_BUFFER_SIZE) {
+			for (i = 0; i < n; i++)
+				rspi_write8(rspi, *data++, RSPI_SPDR);
+			if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
+						    SPCR_SPRIE) < 0) {
+				dev_err(&rspi->master->dev,
+					"%s: receive timeout\n", __func__);
+				return -ETIMEDOUT;
+			}
+			for (i = 0; i < n; i++)
+				rspi_read8(rspi, RSPI_SPDR);
+		} else {
+			for (i = 0; i < n; i++) {
+				if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF,
+							    SPCR_SPTIE) < 0) {
+					dev_err(&rspi->master->dev,
+					   "%s: tx empty timeout\n", __func__);
+				return -ETIMEDOUT;
+				}
+				rspi_write8(rspi, *data++, RSPI_SPDR);
+
+				if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
+							    SPCR_SPRIE) < 0) {
+					dev_err(&rspi->master->dev,
+					   "%s: receive timeout\n", __func__);
+				return -ETIMEDOUT;
+				}
+				rspi_read8(rspi, RSPI_SPDR);
+			}
 		}
-		rspi_read8(rspi, RSPI_SPDR);
-
-		remain--;
+		remain -= n;
 	}
 
 	/* Waiting for the last transmission */
@@ -603,6 +680,7 @@  static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
 {
 	int remain = t->len;
 	u8 *data;
+	int i, n;
 
 	qspi_receive_init(rspi);
 
@@ -614,17 +692,43 @@  static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
 				"%s: tx empty timeout\n", __func__);
 			return -ETIMEDOUT;
 		}
-		/* dummy write for generate clock */
-		rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR);
-
-		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
-			dev_err(&rspi->master->dev,
-				"%s: receive timeout\n", __func__);
-			return -ETIMEDOUT;
+		n = qspi_set_receive_trigger(rspi, remain);
+		if (n >= QSPI_BUFFER_SIZE) {
+			/* dummy write for generate clock */
+			for (i = 0; i < n; i++)
+				rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR);
+
+			if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
+						    SPCR_SPRIE) < 0) {
+				dev_err(&rspi->master->dev,
+					"%s: receive timeout\n", __func__);
+				return -ETIMEDOUT;
+			}
+			/* SPDR allows 8, 16 or 32-bit access */
+			for (i = 0; i < n; i++)
+				*data++ = rspi_read8(rspi, RSPI_SPDR);
+		} else {
+			for (i = 0; i < n; i++) {
+				if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF,
+							    SPCR_SPTIE) < 0) {
+					dev_err(&rspi->master->dev,
+					   "%s: tx empty timeout\n", __func__);
+					return -ETIMEDOUT;
+				}
+				/* dummy write for generate clock */
+				rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR);
+
+				if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
+							    SPCR_SPRIE) < 0) {
+					dev_err(&rspi->master->dev,
+					   "%s: receive timeout\n", __func__);
+					return -ETIMEDOUT;
+				}
+				/* SPDR allows 8, 16 or 32-bit access */
+				*data++ = rspi_read8(rspi, RSPI_SPDR);
+			}
 		}
-		/* SPDR allows 8, 16 or 32-bit access */
-		*data++ = rspi_read8(rspi, RSPI_SPDR);
-		remain--;
+		remain -= n;
 	}
 
 	return 0;