diff mbox

[RFC,1/5] spi: introduce flag for memory mapped read

Message ID 1438072876-16338-2-git-send-email-vigneshr@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Vignesh Raghavendra July 28, 2015, 8:41 a.m. UTC
TI QSPI controller has SFI translator which exposes entire flash memory
as memory mapped region for read. With this interface, the CPU
can copy data from flash using normal memcpy call. SFI translator
takes care of generating appropriate SPI signals to read data from
flash. This interface works only with SPI flash memories and cannot be
used with other SPI devices.
Introduce use_mmap_read field in spi_message struct. This can be set by
mtd devices (m25p80) to indicate to spi-master (ti-qspi) to perform
memory mapped read. This helps to distinguish whether the spi-message is
from mtd layer(hence mmap read is possible) or by other spi devices.

Signed-off-by: Vignesh R <vigneshr@ti.com>
---
 include/linux/spi/spi.h | 3 +++
 1 file changed, 3 insertions(+)

Comments

Mark Brown July 31, 2015, 6:17 p.m. UTC | #1
On Tue, Jul 28, 2015 at 02:11:12PM +0530, Vignesh R wrote:

> Introduce use_mmap_read field in spi_message struct. This can be set by
> mtd devices (m25p80) to indicate to spi-master (ti-qspi) to perform
> memory mapped read. This helps to distinguish whether the spi-message is
> from mtd layer(hence mmap read is possible) or by other spi devices.

Based on this description and...

> + * @use_mmap_mode: Indicate to spi master to perform memory mapped
> + *	read if possible.

...the internal documentation I unable to tell what is meant by "perform
a memory mapped read", at least to the extent where it is visible
outside of the driver.  This means we can't really use this as a generic
API since other people won't be able to tell what it does.
Vignesh Raghavendra Aug. 3, 2015, 4:57 a.m. UTC | #2
Hi,

On 7/31/2015 11:47 PM, Mark Brown wrote:
> On Tue, Jul 28, 2015 at 02:11:12PM +0530, Vignesh R wrote:
> 
>> Introduce use_mmap_read field in spi_message struct. This can be set by
>> mtd devices (m25p80) to indicate to spi-master (ti-qspi) to perform
>> memory mapped read. This helps to distinguish whether the spi-message is
>> from mtd layer(hence mmap read is possible) or by other spi devices.
> 
> Based on this description and...
> 
>> + * @use_mmap_mode: Indicate to spi master to perform memory mapped
>> + *	read if possible.
> 
> ...the internal documentation I unable to tell what is meant by "perform
> a memory mapped read", at least to the extent where it is visible
> outside of the driver.  This means we can't really use this as a generic
> API since other people won't be able to tell what it does.
> 


Will the following documentation provide better idea regarding the flag:

@use_mmap_mode: Some SPI controller chips are optimized for interacting
with serial flash memories. These chips have memory mapped interface,
through which entire serial flash memory slave can be read/written as if
though they are physical memories (like RAM). Using this interface,
flash can be accessed using memcpy() function and the spi controller
hardware will take care of communicating with serial flash over SPI.
Setting this flag will indicate the SPI controller driver that the
spi_message is from mtd layer to read from/write to flash. The SPI
master driver can then appropriately switch the controller to memory
mapped interface to read from/write to flash, based on this flag (See
drivers/spi/spi-ti-qspi.c for example).
NOTE: If the SPI controller chip lacks memory mapped interface, then the
driver will ignore this flag and use normal SPI protocol to read
from/write to flash. Communication with non-flash SPI devices is not
possible using the memory mapped interface.

I can update the patch commit message and documentation accordingly?

Regards
Vignesh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 4, 2015, 3:51 p.m. UTC | #3
On Mon, Aug 03, 2015 at 10:27:19AM +0530, Vignesh R wrote:

> @use_mmap_mode: Some SPI controller chips are optimized for interacting
> with serial flash memories. These chips have memory mapped interface,
> through which entire serial flash memory slave can be read/written as if
> though they are physical memories (like RAM). Using this interface,
> flash can be accessed using memcpy() function and the spi controller
> hardware will take care of communicating with serial flash over SPI.
> Setting this flag will indicate the SPI controller driver that the
> spi_message is from mtd layer to read from/write to flash. The SPI
> master driver can then appropriately switch the controller to memory
> mapped interface to read from/write to flash, based on this flag (See
> drivers/spi/spi-ti-qspi.c for example).
> NOTE: If the SPI controller chip lacks memory mapped interface, then the
> driver will ignore this flag and use normal SPI protocol to read
> from/write to flash. Communication with non-flash SPI devices is not
> possible using the memory mapped interface.

I still can't tell from the above what this interface is supposed to do.
It sounds like the use of memory mapped mode is supposed to be
transparent to users, it should just affect how the controller interacts
with the hardware, but if that's the case why do we need to expose it to
users at all?  Shouldn't the driver just use memory mapped mode if it's
faster?
Vignesh Raghavendra Aug. 4, 2015, 5:59 p.m. UTC | #4
On 8/4/2015 9:21 PM, Mark Brown wrote:
> On Mon, Aug 03, 2015 at 10:27:19AM +0530, Vignesh R wrote:
> 
>> @use_mmap_mode: Some SPI controller chips are optimized for interacting
>> with serial flash memories. These chips have memory mapped interface,
>> through which entire serial flash memory slave can be read/written as if
>> though they are physical memories (like RAM). Using this interface,
>> flash can be accessed using memcpy() function and the spi controller
>> hardware will take care of communicating with serial flash over SPI.
>> Setting this flag will indicate the SPI controller driver that the
>> spi_message is from mtd layer to read from/write to flash. The SPI
>> master driver can then appropriately switch the controller to memory
>> mapped interface to read from/write to flash, based on this flag (See
>> drivers/spi/spi-ti-qspi.c for example).
>> NOTE: If the SPI controller chip lacks memory mapped interface, then the
>> driver will ignore this flag and use normal SPI protocol to read
>> from/write to flash. Communication with non-flash SPI devices is not
>> possible using the memory mapped interface.
> 
> I still can't tell from the above what this interface is supposed to do.
> It sounds like the use of memory mapped mode is supposed to be
> transparent to users, it should just affect how the controller interacts
> with the hardware, but if that's the case why do we need to expose it to
> users at all?  Shouldn't the driver just use memory mapped mode if it's
> faster?
> 

TI QSPI controller has two blocks:
1. SPI_CORE: This is generic(normal) spi mode. This can be used to
communicate with any SPI devices (serial flashes as well as non-flash
devices like touchscreen).
2. SFI_MM_IF(SPI memory mapped interface): The SFI_MM_IF block only
allows reading and writing to an SPI flash device only. Used to speed up
flash reads. It _cannot_ be used to communicate with non flash devices.
Now, the spi_message that ti-qspi receives in transfer_one() callback
can be from mtd device(in which case SFI_MM_IF can be used) or from any
other non flash SPI device (in which case SFI_MM_IF must not be used
instead SPI_CORE is to be used) but there is no way(is there?) to
distinguish where spi_message is from. Therefore I introduced flag
(use_mmap_mode) to struct spi_message. mtd driver will set flag to true,
this helps the ti-qspi driver to determine that the user is flash device
and thus can do read via SFI_MM_IF. If this flag is not set then the
user is assumed to be non flash SPI driver and will use SPI_CORE block
to communicate.

On the whole, I just need a way to determine that the user is a flash
device in order to switch to memory mapped interface.

Regards
Vignesh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Michal Suchanek Aug. 5, 2015, 5:21 a.m. UTC | #5
Hello,

On 4 August 2015 at 19:59, R, Vignesh <vigneshr@ti.com> wrote:
>
>
> On 8/4/2015 9:21 PM, Mark Brown wrote:
>> On Mon, Aug 03, 2015 at 10:27:19AM +0530, Vignesh R wrote:
>>
>>> @use_mmap_mode: Some SPI controller chips are optimized for interacting
>>> with serial flash memories. These chips have memory mapped interface,
>>> through which entire serial flash memory slave can be read/written as if
>>> though they are physical memories (like RAM). Using this interface,
>>> flash can be accessed using memcpy() function and the spi controller
>>> hardware will take care of communicating with serial flash over SPI.
>>> Setting this flag will indicate the SPI controller driver that the
>>> spi_message is from mtd layer to read from/write to flash. The SPI
>>> master driver can then appropriately switch the controller to memory
>>> mapped interface to read from/write to flash, based on this flag (See
>>> drivers/spi/spi-ti-qspi.c for example).
>>> NOTE: If the SPI controller chip lacks memory mapped interface, then the
>>> driver will ignore this flag and use normal SPI protocol to read
>>> from/write to flash. Communication with non-flash SPI devices is not
>>> possible using the memory mapped interface.
>>
>> I still can't tell from the above what this interface is supposed to do.
>> It sounds like the use of memory mapped mode is supposed to be
>> transparent to users, it should just affect how the controller interacts
>> with the hardware, but if that's the case why do we need to expose it to
>> users at all?  Shouldn't the driver just use memory mapped mode if it's
>> faster?
>>
>
> TI QSPI controller has two blocks:
> 1. SPI_CORE: This is generic(normal) spi mode. This can be used to
> communicate with any SPI devices (serial flashes as well as non-flash
> devices like touchscreen).
> 2. SFI_MM_IF(SPI memory mapped interface): The SFI_MM_IF block only
> allows reading and writing to an SPI flash device only. Used to speed up
> flash reads. It _cannot_ be used to communicate with non flash devices.
> Now, the spi_message that ti-qspi receives in transfer_one() callback
> can be from mtd device(in which case SFI_MM_IF can be used) or from any
> other non flash SPI device (in which case SFI_MM_IF must not be used
> instead SPI_CORE is to be used) but there is no way(is there?) to
> distinguish where spi_message is from. Therefore I introduced flag
> (use_mmap_mode) to struct spi_message. mtd driver will set flag to true,
> this helps the ti-qspi driver to determine that the user is flash device
> and thus can do read via SFI_MM_IF. If this flag is not set then the
> user is assumed to be non flash SPI driver and will use SPI_CORE block
> to communicate.
>
> On the whole, I just need a way to determine that the user is a flash
> device in order to switch to memory mapped interface.
>

Maybe it can be set on the SPI slave rather than each message.

Thanks

Michal
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vignesh Raghavendra Aug. 5, 2015, 5:35 a.m. UTC | #6
On 08/05/2015 10:51 AM, Michal Suchanek wrote:
> Hello,
> 
> On 4 August 2015 at 19:59, R, Vignesh <vigneshr@ti.com> wrote:
>>
>>
>> On 8/4/2015 9:21 PM, Mark Brown wrote:
>>> On Mon, Aug 03, 2015 at 10:27:19AM +0530, Vignesh R wrote:
>>>
>>>> @use_mmap_mode: Some SPI controller chips are optimized for interacting
>>>> with serial flash memories. These chips have memory mapped interface,
>>>> through which entire serial flash memory slave can be read/written as if
>>>> though they are physical memories (like RAM). Using this interface,
>>>> flash can be accessed using memcpy() function and the spi controller
>>>> hardware will take care of communicating with serial flash over SPI.
>>>> Setting this flag will indicate the SPI controller driver that the
>>>> spi_message is from mtd layer to read from/write to flash. The SPI
>>>> master driver can then appropriately switch the controller to memory
>>>> mapped interface to read from/write to flash, based on this flag (See
>>>> drivers/spi/spi-ti-qspi.c for example).
>>>> NOTE: If the SPI controller chip lacks memory mapped interface, then the
>>>> driver will ignore this flag and use normal SPI protocol to read
>>>> from/write to flash. Communication with non-flash SPI devices is not
>>>> possible using the memory mapped interface.
>>>
>>> I still can't tell from the above what this interface is supposed to do.
>>> It sounds like the use of memory mapped mode is supposed to be
>>> transparent to users, it should just affect how the controller interacts
>>> with the hardware, but if that's the case why do we need to expose it to
>>> users at all?  Shouldn't the driver just use memory mapped mode if it's
>>> faster?
>>>
>>
>> TI QSPI controller has two blocks:
>> 1. SPI_CORE: This is generic(normal) spi mode. This can be used to
>> communicate with any SPI devices (serial flashes as well as non-flash
>> devices like touchscreen).
>> 2. SFI_MM_IF(SPI memory mapped interface): The SFI_MM_IF block only
>> allows reading and writing to an SPI flash device only. Used to speed up
>> flash reads. It _cannot_ be used to communicate with non flash devices.
>> Now, the spi_message that ti-qspi receives in transfer_one() callback
>> can be from mtd device(in which case SFI_MM_IF can be used) or from any
>> other non flash SPI device (in which case SFI_MM_IF must not be used
>> instead SPI_CORE is to be used) but there is no way(is there?) to
>> distinguish where spi_message is from. Therefore I introduced flag
>> (use_mmap_mode) to struct spi_message. mtd driver will set flag to true,
>> this helps the ti-qspi driver to determine that the user is flash device
>> and thus can do read via SFI_MM_IF. If this flag is not set then the
>> user is assumed to be non flash SPI driver and will use SPI_CORE block
>> to communicate.
>>
>> On the whole, I just need a way to determine that the user is a flash
>> device in order to switch to memory mapped interface.
>>
> 
> Maybe it can be set on the SPI slave rather than each message.

You mean to add flag to spi_device struct? That's ok for me.
Michal Suchanek Aug. 5, 2015, 5:57 a.m. UTC | #7
On 5 August 2015 at 07:35, Vignesh R <vigneshr@ti.com> wrote:
>
>
> On 08/05/2015 10:51 AM, Michal Suchanek wrote:
>> Hello,
>>
>> On 4 August 2015 at 19:59, R, Vignesh <vigneshr@ti.com> wrote:
>>>
>>>
>>> On 8/4/2015 9:21 PM, Mark Brown wrote:
>>>> On Mon, Aug 03, 2015 at 10:27:19AM +0530, Vignesh R wrote:
>>>>

>>>
>>> TI QSPI controller has two blocks:
>>> 1. SPI_CORE: This is generic(normal) spi mode. This can be used to
>>> communicate with any SPI devices (serial flashes as well as non-flash
>>> devices like touchscreen).
>>> 2. SFI_MM_IF(SPI memory mapped interface): The SFI_MM_IF block only
>>> allows reading and writing to an SPI flash device only. Used to speed up
>>> flash reads. It _cannot_ be used to communicate with non flash devices.
>>> Now, the spi_message that ti-qspi receives in transfer_one() callback
>>> can be from mtd device(in which case SFI_MM_IF can be used) or from any
>>> other non flash SPI device (in which case SFI_MM_IF must not be used
>>> instead SPI_CORE is to be used) but there is no way(is there?) to
>>> distinguish where spi_message is from. Therefore I introduced flag
>>> (use_mmap_mode) to struct spi_message. mtd driver will set flag to true,
>>> this helps the ti-qspi driver to determine that the user is flash device
>>> and thus can do read via SFI_MM_IF. If this flag is not set then the
>>> user is assumed to be non flash SPI driver and will use SPI_CORE block
>>> to communicate.
>>>
>>> On the whole, I just need a way to determine that the user is a flash
>>> device in order to switch to memory mapped interface.
>>>
>>
>> Maybe it can be set on the SPI slave rather than each message.
>
> You mean to add flag to spi_device struct? That's ok for me.
>

There are already mode flags so you can just add one more.

Thanks

Michal
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 5, 2015, 11:50 a.m. UTC | #8
On Tue, Aug 04, 2015 at 11:29:52PM +0530, R, Vignesh wrote:
> On 8/4/2015 9:21 PM, Mark Brown wrote:
> > On Mon, Aug 03, 2015 at 10:27:19AM +0530, Vignesh R wrote:

> > I still can't tell from the above what this interface is supposed to do.
> > It sounds like the use of memory mapped mode is supposed to be
> > transparent to users, it should just affect how the controller interacts
> > with the hardware, but if that's the case why do we need to expose it to
> > users at all?  Shouldn't the driver just use memory mapped mode if it's
> > faster?

> 2. SFI_MM_IF(SPI memory mapped interface): The SFI_MM_IF block only
> allows reading and writing to an SPI flash device only. Used to speed up
> flash reads. It _cannot_ be used to communicate with non flash devices.
> Now, the spi_message that ti-qspi receives in transfer_one() callback
> can be from mtd device(in which case SFI_MM_IF can be used) or from any
> other non flash SPI device (in which case SFI_MM_IF must not be used
> instead SPI_CORE is to be used) but there is no way(is there?) to
> distinguish where spi_message is from. Therefore I introduced flag
> (use_mmap_mode) to struct spi_message. mtd driver will set flag to true,
> this helps the ti-qspi driver to determine that the user is flash device
> and thus can do read via SFI_MM_IF. If this flag is not set then the
> user is assumed to be non flash SPI driver and will use SPI_CORE block
> to communicate.

So if you're trying to do this you need to document it adequately so
that other people can understand what it is supposed to do and how to
use and implement it.  People can't really tell how the interface is
supposed to work based on what was in the patch and the above isn't
really helping.  For example, how does this change or restrict what the
contents of the spi_message are?

> On the whole, I just need a way to determine that the user is a flash
> device in order to switch to memory mapped interface.

As far as I can tell you want to set a per spi_message flag saying that
the message is a flash read command?  If that's what this is trying to
do then why do you need to set the flag at all?  If the message is in a
clearly defined format and it's more efficient to use this mmap mode
then surely the driver can just recognise that the format is approprate
and switch into mmap mode without being explicitly told - I'm not clear
what the flag adds here.
Michal Suchanek Aug. 5, 2015, 12:40 p.m. UTC | #9
On 5 August 2015 at 13:50, Mark Brown <broonie@kernel.org> wrote:
> On Tue, Aug 04, 2015 at 11:29:52PM +0530, R, Vignesh wrote:
>> On 8/4/2015 9:21 PM, Mark Brown wrote:
>> > On Mon, Aug 03, 2015 at 10:27:19AM +0530, Vignesh R wrote:
>
>> > I still can't tell from the above what this interface is supposed to do.
>> > It sounds like the use of memory mapped mode is supposed to be
>> > transparent to users, it should just affect how the controller interacts
>> > with the hardware, but if that's the case why do we need to expose it to
>> > users at all?  Shouldn't the driver just use memory mapped mode if it's
>> > faster?
>
>> 2. SFI_MM_IF(SPI memory mapped interface): The SFI_MM_IF block only
>> allows reading and writing to an SPI flash device only. Used to speed up
>> flash reads. It _cannot_ be used to communicate with non flash devices.
>> Now, the spi_message that ti-qspi receives in transfer_one() callback
>> can be from mtd device(in which case SFI_MM_IF can be used) or from any
>> other non flash SPI device (in which case SFI_MM_IF must not be used
>> instead SPI_CORE is to be used) but there is no way(is there?) to
>> distinguish where spi_message is from. Therefore I introduced flag
>> (use_mmap_mode) to struct spi_message. mtd driver will set flag to true,
>> this helps the ti-qspi driver to determine that the user is flash device
>> and thus can do read via SFI_MM_IF. If this flag is not set then the
>> user is assumed to be non flash SPI driver and will use SPI_CORE block
>> to communicate.
>
> So if you're trying to do this you need to document it adequately so
> that other people can understand what it is supposed to do and how to
> use and implement it.  People can't really tell how the interface is
> supposed to work based on what was in the patch and the above isn't
> really helping.  For example, how does this change or restrict what the
> contents of the spi_message are?
>
>> On the whole, I just need a way to determine that the user is a flash
>> device in order to switch to memory mapped interface.
>
> As far as I can tell you want to set a per spi_message flag saying that
> the message is a flash read command?  If that's what this is trying to
> do then why do you need to set the flag at all?  If the message is in a
> clearly defined format and it's more efficient to use this mmap mode
> then surely the driver can just recognise that the format is approprate
> and switch into mmap mode without being explicitly told - I'm not clear
> what the flag adds here.

ehm, the read command is just one byte.

I don't think sending 03 or other random byte as the first byte of a
SPI transfer can be used as reliable detection that we are talking to
a SPI flash memory.

Thanks

Michal
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 5, 2015, 12:44 p.m. UTC | #10
On Wed, Aug 05, 2015 at 02:40:01PM +0200, Michal Suchanek wrote:
> On 5 August 2015 at 13:50, Mark Brown <broonie@kernel.org> wrote:

> > As far as I can tell you want to set a per spi_message flag saying that
> > the message is a flash read command?  If that's what this is trying to
> > do then why do you need to set the flag at all?  If the message is in a
> > clearly defined format and it's more efficient to use this mmap mode
> > then surely the driver can just recognise that the format is approprate
> > and switch into mmap mode without being explicitly told - I'm not clear
> > what the flag adds here.

> ehm, the read command is just one byte.

> I don't think sending 03 or other random byte as the first byte of a
> SPI transfer can be used as reliable detection that we are talking to
> a SPI flash memory.

Why care - if something is physically in the same format as a flash read
command how would a device be able to tell that it wasn't actually a
flash read command?  The signals sent on the bus are going to be
identical anyway.
Michal Suchanek Aug. 5, 2015, 12:56 p.m. UTC | #11
On 5 August 2015 at 14:44, Mark Brown <broonie@kernel.org> wrote:
> On Wed, Aug 05, 2015 at 02:40:01PM +0200, Michal Suchanek wrote:
>> On 5 August 2015 at 13:50, Mark Brown <broonie@kernel.org> wrote:
>
>> > As far as I can tell you want to set a per spi_message flag saying that
>> > the message is a flash read command?  If that's what this is trying to
>> > do then why do you need to set the flag at all?  If the message is in a
>> > clearly defined format and it's more efficient to use this mmap mode
>> > then surely the driver can just recognise that the format is approprate
>> > and switch into mmap mode without being explicitly told - I'm not clear
>> > what the flag adds here.
>
>> ehm, the read command is just one byte.
>
>> I don't think sending 03 or other random byte as the first byte of a
>> SPI transfer can be used as reliable detection that we are talking to
>> a SPI flash memory.
>
> Why care - if something is physically in the same format as a flash read
> command how would a device be able to tell that it wasn't actually a
> flash read command?  The signals sent on the bus are going to be
> identical anyway.

Not only must the command be the same but also the response must be tha same.

The flash chip responds by sending arbitrary amount of data. Given
that transfer_one gets only the part that sends the read command and
the part to do the actual read may or may not follow this is getting a
bit hairy. Add in dummy bytes due to fast-read lag and page write
wrap-around and you get something that you definitely do not want
unless you are really sure that there is a flash memory on the other
end of the wire.

Thanks

Michal
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 6, 2015, 9:02 a.m. UTC | #12
On Wed, Aug 05, 2015 at 02:56:09PM +0200, Michal Suchanek wrote:
> On 5 August 2015 at 14:44, Mark Brown <broonie@kernel.org> wrote:
> > On Wed, Aug 05, 2015 at 02:40:01PM +0200, Michal Suchanek wrote:

> >> I don't think sending 03 or other random byte as the first byte of a
> >> SPI transfer can be used as reliable detection that we are talking to
> >> a SPI flash memory.

> > Why care - if something is physically in the same format as a flash read
> > command how would a device be able to tell that it wasn't actually a
> > flash read command?  The signals sent on the bus are going to be
> > identical anyway.

> Not only must the command be the same but also the response must be tha same.

What difference would that make?  The caller is sending a single SPI
operation and this is a user visible thing...

> The flash chip responds by sending arbitrary amount of data. Given
> that transfer_one gets only the part that sends the read command and
> the part to do the actual read may or may not follow this is getting a
> bit hairy. Add in dummy bytes due to fast-read lag and page write
> wrap-around and you get something that you definitely do not want
> unless you are really sure that there is a flash memory on the other
> end of the wire.

So if you're doing this you may have a good reason to implement
transfer_one_message() instead.  Or perhaps implement it in the core and
provide operations to do the map and unmap.  And of course if this sort
of requirement exists that's an obvious thing that must be documented
in the interfaces but isn't.

We need a lot more thought about the interface here, the lack of any
explanation of what the interface is supposed to be and the fact that
all questions about it are being answered in terms of describing the
specific system are both a bit worrying.
Michal Suchanek Aug. 6, 2015, 10:01 a.m. UTC | #13
On 6 August 2015 at 11:02, Mark Brown <broonie@kernel.org> wrote:
> On Wed, Aug 05, 2015 at 02:56:09PM +0200, Michal Suchanek wrote:
>> On 5 August 2015 at 14:44, Mark Brown <broonie@kernel.org> wrote:
>> > On Wed, Aug 05, 2015 at 02:40:01PM +0200, Michal Suchanek wrote:
>
>> >> I don't think sending 03 or other random byte as the first byte of a
>> >> SPI transfer can be used as reliable detection that we are talking to
>> >> a SPI flash memory.
>
>> > Why care - if something is physically in the same format as a flash read
>> > command how would a device be able to tell that it wasn't actually a
>> > flash read command?  The signals sent on the bus are going to be
>> > identical anyway.
>
>> Not only must the command be the same but also the response must be tha same.
>
> What difference would that make?  The caller is sending a single SPI
> operation and this is a user visible thing...
>
>> The flash chip responds by sending arbitrary amount of data. Given
>> that transfer_one gets only the part that sends the read command and
>> the part to do the actual read may or may not follow this is getting a
>> bit hairy. Add in dummy bytes due to fast-read lag and page write
>> wrap-around and you get something that you definitely do not want
>> unless you are really sure that there is a flash memory on the other
>> end of the wire.
>
> So if you're doing this you may have a good reason to implement
> transfer_one_message() instead.  Or perhaps implement it in the core and
> provide operations to do the map and unmap.  And of course if this sort
> of requirement exists that's an obvious thing that must be documented
> in the interfaces but isn't.
>
> We need a lot more thought about the interface here, the lack of any
> explanation of what the interface is supposed to be and the fact that
> all questions about it are being answered in terms of describing the
> specific system are both a bit worrying.

Disclaimer: I am not familiar with the hardware for which this patch
adds support.

However, I am familiar m25p80.c and as I understand it the controller
is basically supposed to implement m25p80.c in hardware when this flag
is set.

If I was using m25p80.c to talk to anything but an actual flash chip
it would get me quite worried.

Thanks

Michal
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Russell King - ARM Linux Aug. 6, 2015, 10:22 a.m. UTC | #14
On Thu, Aug 06, 2015 at 12:01:37PM +0200, Michal Suchanek wrote:
> Disclaimer: I am not familiar with the hardware for which this patch
> adds support.
> 
> However, I am familiar m25p80.c and as I understand it the controller
> is basically supposed to implement m25p80.c in hardware when this flag
> is set.

That, to me, sounds like what you have is:

---m25p80 specific interface--->SPI bus--->m25p80 device

Where the m25p80 specific interface does not expose direct access to the
SPI bus?

If that's the case, then maybe you should consider whether using the SPI
bus infrastructure is really the best way forward.  Would it make more
sense instead to adopt a different software structure, something more
high-level like:

     +-------------------------------------------+
     |          m25p80 high-level driver         |
     +----------------------+--------------------+
     |   SPI m25p80 driver  |                    |
     +----------------------+                    |
     |      SPI layer       |  Special driver    |
     +----------------------+                    |
     |    SPI bus driver    |                    |
     +----------------------+--------------------+
     |     SPI hardware     |  Special hardware  |
     +----------------------+--------------------+

Rather than what you seem to be trying to do, which seems to be:

     +----------------------+
     |   SPI m25p80 driver  |
     +----------------------+
     |      SPI layer       |
     +----------------------+
     |  Translation driver  |
     +----------------------+
     |   Special hardware   |
     +----------------------+

where this requires M25P80 specific hacks to be introduced into the SPI
layer so that you can communicate additional information between the SPI
M25P80 driver and the translation driver.
Mark Brown Aug. 6, 2015, 11 a.m. UTC | #15
On Thu, Aug 06, 2015 at 11:22:25AM +0100, Russell King - ARM Linux wrote:

> If that's the case, then maybe you should consider whether using the SPI
> bus infrastructure is really the best way forward.  Would it make more
> sense instead to adopt a different software structure, something more
> high-level like:

>      +-------------------------------------------+
>      |          m25p80 high-level driver         |
>      +----------------------+--------------------+
>      |   SPI m25p80 driver  |                    |
>      +----------------------+                    |
>      |      SPI layer       |  Special driver    |
>      +----------------------+                    |
>      |    SPI bus driver    |                    |
>      +----------------------+--------------------+
>      |     SPI hardware     |  Special hardware  |
>      +----------------------+--------------------+

Yes, that's what's been talked about before - for some of these devices
they're sufficiently flash specialist that we just don't bother exposing
a SPI interface at all though AIUI they could be persuaded to do it.  It
isn't entirely clear that we want exactly that split, if the devices are
reasonable SPI controllers we will want to handle the case where they
have flash and non-flash devices on the same bus.  For that there is
going to be some generalisable work possible for managing switching
between memory mapped and SPI modes where those are mutually exclusive,
especially if the switch between them isn't free.
Michal Suchanek Aug. 6, 2015, 11:02 a.m. UTC | #16
On 6 August 2015 at 12:22, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Aug 06, 2015 at 12:01:37PM +0200, Michal Suchanek wrote:
>> Disclaimer: I am not familiar with the hardware for which this patch
>> adds support.
>>
>> However, I am familiar m25p80.c and as I understand it the controller
>> is basically supposed to implement m25p80.c in hardware when this flag
>> is set.
>
> That, to me, sounds like what you have is:
>
> ---m25p80 specific interface--->SPI bus--->m25p80 device
>
> Where the m25p80 specific interface does not expose direct access to the
> SPI bus?

The m25p80 specific hardware interface is presumably optional so you
can use it or not. The description is a bit vague, though.

In fsl-qspi the driver does not make it optional. I am not sure that
controller can be used for non-m25p80 slaves.


>
> If that's the case, then maybe you should consider whether using the SPI
> bus infrastructure is really the best way forward.  Would it make more
> sense instead to adopt a different software structure, something more
> high-level like:
>
>      +-------------------------------------------+
>      |          m25p80 high-level driver      =spi-nor   |
>      +----------------------+--------------------+
>      |   SPI m25p80 driver  |                    |
>      +----------------------+                    |
>      |      SPI layer       |  Special driver    =fsl-qspi|
>      +----------------------+                    |
>      |    SPI bus driver    |                    |
>      +----------------------+--------------------+
>      |     SPI hardware     |  Special hardware  |
>      +----------------------+--------------------+
>

Thanks

Michal
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 6, 2015, 11:23 a.m. UTC | #17
On Thu, Aug 06, 2015 at 12:01:37PM +0200, Michal Suchanek wrote:

> However, I am familiar m25p80.c and as I understand it the controller
> is basically supposed to implement m25p80.c in hardware when this flag
> is set.

But what in concrete terms is that supposed to mean?  It's currently
just an essentially undocumented flag on a message rather than something
operating at the level of a flash chip.  That's pretty much where
Russell's comments come from.

> If I was using m25p80.c to talk to anything but an actual flash chip
> it would get me quite worried.

Sure, but at the end of the day it's just emitting standard SPI messages
which don't know anything about flash.  If those messages are a sensible
interface here then why bother with the flag, we can just pattern match
on the format of the message.  If that doesn't work then probably this
isn't a great interface and a separate, application specific interface
makes more sense.
Michal Suchanek Aug. 6, 2015, 11:42 a.m. UTC | #18
On 6 August 2015 at 13:23, Mark Brown <broonie@kernel.org> wrote:
> On Thu, Aug 06, 2015 at 12:01:37PM +0200, Michal Suchanek wrote:
>
>> However, I am familiar m25p80.c and as I understand it the controller
>> is basically supposed to implement m25p80.c in hardware when this flag
>> is set.
>
> But what in concrete terms is that supposed to mean?  It's currently
> just an essentially undocumented flag on a message rather than something
> operating at the level of a flash chip.  That's pretty much where
> Russell's comments come from.
>
>> If I was using m25p80.c to talk to anything but an actual flash chip
>> it would get me quite worried.
>
> Sure, but at the end of the day it's just emitting standard SPI messages
> which don't know anything about flash.  If those messages are a sensible
> interface here then why bother with the flag, we can just pattern match
> on the format of the message.  If that doesn't work then probably this
> isn't a great interface and a separate, application specific interface
> makes more sense.

The messages are sensible interface for communicating with a device
that interprets a particular part of the mesasge as address and
another particular part of the message as command and sends same
amount of junk before reply as the flash chip would. If your device
happens to send reply immediately part of it is trashed. If it happens
to interpret address differently the data ends up in random part of
your memory. So no, that is not something you can autodetect.

At the end of the day you have valid SPI messages but the m25p80 layer
adds interpretation to those messages which may not always give
correct result.

On the other hand, if you ever get to m25p80 or spi-nor you can assume
any message you send goes to a flash chip and insist that the
controller uses the flash-specific interface.

If there is possibility of connecting different kind of devices to
multiple chipselects on the same master then you probably want to
select this option per message or per slave.

Thanks

Michal
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vignesh Raghavendra Aug. 6, 2015, 12:25 p.m. UTC | #19
On 08/06/2015 03:52 PM, Russell King - ARM Linux wrote:
> On Thu, Aug 06, 2015 at 12:01:37PM +0200, Michal Suchanek wrote:
>> Disclaimer: I am not familiar with the hardware for which this patch
>> adds support.
>>
>> However, I am familiar m25p80.c and as I understand it the controller
>> is basically supposed to implement m25p80.c in hardware when this flag
>> is set.
> 
> That, to me, sounds like what you have is:
> 
> ---m25p80 specific interface--->SPI bus--->m25p80 device
> 
> Where the m25p80 specific interface does not expose direct access to the
> SPI bus?
> 

Let me give overview of ti-qspi controller:

There are two interfaces in the controller, one exposes direct access to
SPI bus and the other doesn't. It is possible to dynamically switch
between these ports by writing to QSPI_SPI_SWITCH_REG.

The two interface are [1]:
1) Generic SPI interface: (config port): with this interface, ti-qspi
controller can communicate with *any* spi device (flash and non-flash).
This interface is provides direct access to SPI bus.

2) SPI memory mapped interface (memory mapped port): This is m25p80
specific interface which can be use to read data from flash.
But if the flash has to be configured to some particular mode like QUAD
READ MODE, then the controller needs to be put in to config port to read
and modify serial flash's config register and then switch to memory
mapped port in order to read data stored on flash.

For example on DRA74 evm, if a 64 MB flash is connected as a slave,
entire flash memory is visible from 0x5C000000 to 0x5FFFFFFF L3_MAIN
address. In order to read using memory mapped port following will be the
sequence:

1.Write to flash config register via config port to switch to QUAD MODE
(or any mode that flash supports).
2. Populate QSPI_SPI_SETUP_REGx with flash read command, number of
address bytes to use and dummy bytes required.
3. Switch to memory mapped port by writing to QSPI_SPI_SWITCH_REG.
4. Now, its possible to perform read from 0x5C000000 to 0x5FFFFFFF using
memcpy. The qspi controller hardware will communicate over SPI bus and
get the data. This data is directly sent to RAM via SoC's interconnect.

Advantages of memory mapped port are: improved read performance,
MEM_TO_MEM DMA support can be added (ti-qspi hardware as such does not
provide DMA events).

Advantages of config port: can be used to communicate with *any* SPI
device, provides direct read/write access to SPI bus.

On the whole following are my requirements:
1. to be able to communicate with non -flash SPI devices via config port
( this functionality is supported by current driver, I dont want to
break it). Or pump any spi_message on to SPI bus directly.
2. take advantage of memory mapped port in order to increase read
throughput( and use dma in future) when the slave is a m25p80 type flash.
3. handle m25p80 as well as other slave on multiple chipselects.

I just need to know whether the user that requested the transfer is
m25p80 driver. If yes, ti-qspi driver can take advantage of memory
mapped interface, else just use config port to access SPI bus directly.

Writing separate driver based on spi-nor framework to interface with
m25p80 is not an option because, I would lose the ability to interface
with non-flash devices.

The spi_message that is received in transfer_one_message() is too
generic to imply the slave device that is on the other side of the wire.
IMO, the read command does not imply that the slave is m25p80 flash
(besides the read opcodes vary across vendors of m25p80 and across modes).

As Michal suggested, adding a flag to spi_device to distinguish whether
the slave is a m25p80 flash type will help spi master to handle
optimizations specific to m25p80s while being generic enough to handle
all other spi devices. Is that ok? Is there any other way to imply what
slave as at the other end?

[1] TRM: http://www.ti.com/lit/ug/spruhz6/spruhz6.pdf 24.5.4 QSPI
Functional Description
Russell King - ARM Linux Aug. 6, 2015, 1:51 p.m. UTC | #20
On Thu, Aug 06, 2015 at 05:55:23PM +0530, Vignesh R wrote:
> On the whole following are my requirements:
> 1. to be able to communicate with non -flash SPI devices via config port
> ( this functionality is supported by current driver, I dont want to
> break it). Or pump any spi_message on to SPI bus directly.
> 2. take advantage of memory mapped port in order to increase read
> throughput( and use dma in future) when the slave is a m25p80 type flash.
> 3. handle m25p80 as well as other slave on multiple chipselects.
> 
> I just need to know whether the user that requested the transfer is
> m25p80 driver. If yes, ti-qspi driver can take advantage of memory
> mapped interface, else just use config port to access SPI bus directly.

The problem with this approach is that it's an abomination.  It's adding
a SPI-user specific hack which is detected by a specific driver.  That's
really not sane - what happens when we have lots of these kinds of "I'm
an X SPI-user" with drivers detecting that?  It's not maintainable in the
long term.

Yes, your requirements _today_ seem simple and easy, but you're only
thinking about today, not tomorrow when you've moved on and someone else
has to maintain the mess left behind (or delete it from mainline because
they're sick of dealing with a hack.)

> The spi_message that is received in transfer_one_message() is too
> generic to imply the slave device that is on the other side of the wire.
> IMO, the read command does not imply that the slave is m25p80 flash
> (besides the read opcodes vary across vendors of m25p80 and across modes).

I can see both sides of the argument.

Mark is saying: if the SPI driver detects that the message to be transmitted
is a read command followed by the appropriate number of dummy bytes, and
then the data being read _and_ it's using quad-mode access, and the hardware
generates _exactly_ that in hardware using the memory mapped mode, there is
no reason _not_ to use the hardware to achieve that SPI transaction.  The
bus activity will be identical to what happens when the SPI controller is
used manually to achieve that bus sequence.

You're saying: but the documentation says you can't use it for anything
except m25p80.  If you look at 24.5.4.1.2, it tells you what the SFI
generates on the bus, which is:

1. CS active
2. Read command byte sent
3. 1-4 address bytes sent
4. 0-3 dummy bytes sent
5. data bytes read from bus
6. CS inactive

So, Mark's point is "if we can detect a transaction which fits _that_
bus activity, there's no reason not to use this acceleration for the
transaction."

What you're failing to counter with is: we don't have enough information
in the SPI driver to know how many dummy bytes there are between the
address bytes and the data read from the bus.

The M25P80 driver just appends additional bytes to the message to
achieve this:

        struct m25p *flash = nor->priv;
        unsigned int dummy = nor->read_dummy;

        /* convert the dummy cycles to the number of bytes */
        dummy /= 8;

        flash->command[0] = nor->read_opcode;
        m25p_addr2cmd(nor, from, flash->command);

        t[0].tx_buf = flash->command;
        t[0].len = m25p_cmdsz(nor) + dummy;
        spi_message_add_tail(&t[0], &m);

The reason that the number of dummy bytes can't be detected is because
it's all hidden in the first transaction as the total number of bytes to
be transmitted - and the dummy bytes are uninitialised, so you can't
make any assumptions what value they are.  There is no way for the SPI
driver to know whether these dummy bytes are dummy bytes or whether they
have an effect on the targetted device.

I think that comprehensively rules out Mark's idea with the SPI core as
it stands today: there is no way for the SPI driver to reliably detect
a message like a SFI read command by parsing the SPI transmitted message
prior to sending it as we can never be sure whether there are dummy bytes
to be transmitted.

What may make more sense from the SPI point of view is to communicate to
all SPI drivers how many dummy bytes are to be transferred.  I'm not fully
up on SPI, but maybe something like this:

	t[0].tx_buf = flash->command;
	t[0].len = m25p_cmdsz(nor);
	spi_message_add_tail(&t[0], &m);
	t[1].tx_buf = dummy_buffer;
	t[1].len = dummy;
	t[1].dummy = 1;
	spi_message_add_tail(&t[1], &m);

This way, we're describing the transfer to the SPI core, and explicitly
indicating that there are some dummy bytes.  The SPI driver can then
tell that these are dummy bytes, and if the SPI message consists of:

- transmit 2 to 5 bytes where the first byte is a recognised read command
- transmit 0 to 3 dummy bytes
- read some bytes

then it can make use of the SFI mode to accelerate the operation.

This would not be a hack to the SPI code: we're describing to the SPI
code what we want to achieve in terms of the activity on the bus, and
providing that level of description then allows the SPI driver to make
informed decisions on whether it can handle the transfer using some
non-standard feature.
Mark Brown Aug. 6, 2015, 4:03 p.m. UTC | #21
On Thu, Aug 06, 2015 at 01:42:32PM +0200, Michal Suchanek wrote:
> On 6 August 2015 at 13:23, Mark Brown <broonie@kernel.org> wrote:

> > Sure, but at the end of the day it's just emitting standard SPI messages
> > which don't know anything about flash.  If those messages are a sensible
> > interface here then why bother with the flag, we can just pattern match
> > on the format of the message.  If that doesn't work then probably this
> > isn't a great interface and a separate, application specific interface
> > makes more sense.

> The messages are sensible interface for communicating with a device
> that interprets a particular part of the mesasge as address and
> another particular part of the message as command and sends same
> amount of junk before reply as the flash chip would. If your device

That's just a statement that it's possible to do things this way, it's
not clear to me that it's an explanation as to why it is sensible to do
so - the obvious thing to do there would be to specify the flash
operation as a flash operation rather than reverse engineer the flash
operation from the wire format.

> happens to send reply immediately part of it is trashed. If it happens
> to interpret address differently the data ends up in random part of
> your memory. So no, that is not something you can autodetect.

If this stuff doesn't appear in the spi_message in some observable form
then I'd expect that any existing flash support is broken since a SPI
controller that doesn't have any acceleration is just going to do what
the message says.

> At the end of the day you have valid SPI messages but the m25p80 layer
> adds interpretation to those messages which may not always give
> correct result.

Which comes back to the thing I keep saying about needing some sort of
information about what the flag means and the questions about why this
is a good interface...

> On the other hand, if you ever get to m25p80 or spi-nor you can assume
> any message you send goes to a flash chip and insist that the
> controller uses the flash-specific interface.

There's an awful lot of flashes out there connected to controllers that
don't implement any sort of acceleration for flash, I'm not convinced
that your assumption there is valid.

> If there is possibility of connecting different kind of devices to
> multiple chipselects on the same master then you probably want to
> select this option per message or per slave.

We definitely need to account for that.
Geert Uytterhoeven Aug. 6, 2015, 4:14 p.m. UTC | #22
On Thu, Aug 6, 2015 at 3:51 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Aug 06, 2015 at 05:55:23PM +0530, Vignesh R wrote:
>> On the whole following are my requirements:
>> 1. to be able to communicate with non -flash SPI devices via config port
>> ( this functionality is supported by current driver, I dont want to
>> break it). Or pump any spi_message on to SPI bus directly.
>> 2. take advantage of memory mapped port in order to increase read
>> throughput( and use dma in future) when the slave is a m25p80 type flash.
>> 3. handle m25p80 as well as other slave on multiple chipselects.
>>
>> I just need to know whether the user that requested the transfer is
>> m25p80 driver. If yes, ti-qspi driver can take advantage of memory
>> mapped interface, else just use config port to access SPI bus directly.
>
> The problem with this approach is that it's an abomination.  It's adding
> a SPI-user specific hack which is detected by a specific driver.  That's
> really not sane - what happens when we have lots of these kinds of "I'm
> an X SPI-user" with drivers detecting that?  It's not maintainable in the
> long term.
>
> Yes, your requirements _today_ seem simple and easy, but you're only
> thinking about today, not tomorrow when you've moved on and someone else
> has to maintain the mess left behind (or delete it from mainline because
> they're sick of dealing with a hack.)
>
>> The spi_message that is received in transfer_one_message() is too
>> generic to imply the slave device that is on the other side of the wire.
>> IMO, the read command does not imply that the slave is m25p80 flash
>> (besides the read opcodes vary across vendors of m25p80 and across modes).
>
> I can see both sides of the argument.
>
> Mark is saying: if the SPI driver detects that the message to be transmitted
> is a read command followed by the appropriate number of dummy bytes, and
> then the data being read _and_ it's using quad-mode access, and the hardware
> generates _exactly_ that in hardware using the memory mapped mode, there is
> no reason _not_ to use the hardware to achieve that SPI transaction.  The
> bus activity will be identical to what happens when the SPI controller is
> used manually to achieve that bus sequence.
>
> You're saying: but the documentation says you can't use it for anything
> except m25p80.  If you look at 24.5.4.1.2, it tells you what the SFI
> generates on the bus, which is:
>
> 1. CS active
> 2. Read command byte sent
> 3. 1-4 address bytes sent
> 4. 0-3 dummy bytes sent
> 5. data bytes read from bus
> 6. CS inactive
>
> So, Mark's point is "if we can detect a transaction which fits _that_
> bus activity, there's no reason not to use this acceleration for the
> transaction."
>
> What you're failing to counter with is: we don't have enough information
> in the SPI driver to know how many dummy bytes there are between the
> address bytes and the data read from the bus.

Irrespective of the dummy bytes.
What if the spi device is not a FLASH ROM, but some other device,
which receives a data packet that accidentally looks like an m25p80 READ
command?

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-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 6, 2015, 4:46 p.m. UTC | #23
On Thu, Aug 06, 2015 at 02:51:29PM +0100, Russell King - ARM Linux wrote:

> The M25P80 driver just appends additional bytes to the message to
> achieve this:
> 
>         struct m25p *flash = nor->priv;
>         unsigned int dummy = nor->read_dummy;
> 
>         /* convert the dummy cycles to the number of bytes */
>         dummy /= 8;
> 
>         flash->command[0] = nor->read_opcode;
>         m25p_addr2cmd(nor, from, flash->command);
> 
>         t[0].tx_buf = flash->command;
>         t[0].len = m25p_cmdsz(nor) + dummy;
>         spi_message_add_tail(&t[0], &m);

> The reason that the number of dummy bytes can't be detected is because
> it's all hidden in the first transaction as the total number of bytes to
> be transmitted - and the dummy bytes are uninitialised, so you can't
> make any assumptions what value they are.  There is no way for the SPI
> driver to know whether these dummy bytes are dummy bytes or whether they
> have an effect on the targetted device.

We *could* (as you suggest below) indicate dummy transfers by having a
separate transfer which omits the transmit buffers though I'd expect
that normally that is going to be a small performance hit if interpreted
directly so we need to think what to do there.  We do get other devices
sending dummy bytes, it's sometimes a requirement for high speed
register access to give settling time for the device, so other things
would get some milage from it.

> What may make more sense from the SPI point of view is to communicate to
> all SPI drivers how many dummy bytes are to be transferred.  I'm not fully
> up on SPI, but maybe something like this:

> 	t[0].tx_buf = flash->command;
> 	t[0].len = m25p_cmdsz(nor);
> 	spi_message_add_tail(&t[0], &m);
> 	t[1].tx_buf = dummy_buffer;
> 	t[1].len = dummy;
> 	t[1].dummy = 1;
> 	spi_message_add_tail(&t[1], &m);

> This way, we're describing the transfer to the SPI core, and explicitly
> indicating that there are some dummy bytes.  The SPI driver can then
> tell that these are dummy bytes, and if the SPI message consists of:

That'd work as well, my first thought would to use NULL as a dummy
buffer pointer and let the core substitute in data for the drivers.  We
currently insist on having at least one buffer but that's fixable.

> This would not be a hack to the SPI code: we're describing to the SPI
> code what we want to achieve in terms of the activity on the bus, and
> providing that level of description then allows the SPI driver to make
> informed decisions on whether it can handle the transfer using some
> non-standard feature.

Yup.
Michal Suchanek Aug. 6, 2015, 6:20 p.m. UTC | #24
On 6 August 2015 at 18:14, Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> On Thu, Aug 6, 2015 at 3:51 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
>> On Thu, Aug 06, 2015 at 05:55:23PM +0530, Vignesh R wrote:
>>> On the whole following are my requirements:
>>> 1. to be able to communicate with non -flash SPI devices via config port
>>> ( this functionality is supported by current driver, I dont want to
>>> break it). Or pump any spi_message on to SPI bus directly.
>>> 2. take advantage of memory mapped port in order to increase read
>>> throughput( and use dma in future) when the slave is a m25p80 type flash.
>>> 3. handle m25p80 as well as other slave on multiple chipselects.
>>>
>>> I just need to know whether the user that requested the transfer is
>>> m25p80 driver. If yes, ti-qspi driver can take advantage of memory
>>> mapped interface, else just use config port to access SPI bus directly.
>>
>> The problem with this approach is that it's an abomination.  It's adding
>> a SPI-user specific hack which is detected by a specific driver.  That's
>> really not sane - what happens when we have lots of these kinds of "I'm
>> an X SPI-user" with drivers detecting that?  It's not maintainable in the
>> long term.
>>
>> Yes, your requirements _today_ seem simple and easy, but you're only
>> thinking about today, not tomorrow when you've moved on and someone else
>> has to maintain the mess left behind (or delete it from mainline because
>> they're sick of dealing with a hack.)
>>
>>> The spi_message that is received in transfer_one_message() is too
>>> generic to imply the slave device that is on the other side of the wire.
>>> IMO, the read command does not imply that the slave is m25p80 flash
>>> (besides the read opcodes vary across vendors of m25p80 and across modes).
>>
>> I can see both sides of the argument.
>>
>> Mark is saying: if the SPI driver detects that the message to be transmitted
>> is a read command followed by the appropriate number of dummy bytes, and
>> then the data being read _and_ it's using quad-mode access, and the hardware
>> generates _exactly_ that in hardware using the memory mapped mode, there is
>> no reason _not_ to use the hardware to achieve that SPI transaction.  The
>> bus activity will be identical to what happens when the SPI controller is
>> used manually to achieve that bus sequence.
>>
>> You're saying: but the documentation says you can't use it for anything
>> except m25p80.  If you look at 24.5.4.1.2, it tells you what the SFI
>> generates on the bus, which is:
>>
>> 1. CS active
>> 2. Read command byte sent
>> 3. 1-4 address bytes sent
>> 4. 0-3 dummy bytes sent
>> 5. data bytes read from bus
>> 6. CS inactive
>>
>> So, Mark's point is "if we can detect a transaction which fits _that_
>> bus activity, there's no reason not to use this acceleration for the
>> transaction."
>>
>> What you're failing to counter with is: we don't have enough information
>> in the SPI driver to know how many dummy bytes there are between the
>> address bytes and the data read from the bus.
>
> Irrespective of the dummy bytes.
> What if the spi device is not a FLASH ROM, but some other device,
> which receives a data packet that accidentally looks like an m25p80 READ
> command?
>

Presumably the driver would interpret some random part of the message
as address and map the reply in your address space at that address
from the flash mmap base.

If you happen to overflow the flash memory mmap space the behaviour
will probably not be well defined.

Thanks

Michal
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 6, 2015, 6:20 p.m. UTC | #25
On Thu, Aug 06, 2015 at 05:55:23PM +0530, Vignesh R wrote:

> 1.Write to flash config register via config port to switch to QUAD MODE
> (or any mode that flash supports).
> 2. Populate QSPI_SPI_SETUP_REGx with flash read command, number of
> address bytes to use and dummy bytes required.

These things being constant for a given flash?

> 3. Switch to memory mapped port by writing to QSPI_SPI_SWITCH_REG.
> 4. Now, its possible to perform read from 0x5C000000 to 0x5FFFFFFF using
> memcpy. The qspi controller hardware will communicate over SPI bus and
> get the data. This data is directly sent to RAM via SoC's interconnect.

Presumably if it's done via memcpy() it won't go direct to RAM but
rather be bounced through the CPU which is a bit interesting for
performance (it might help, but it does mean that there's a core stalled
waiting for the flash which might not be the best use of resources if
there's other things it can be getting on with).  With DMA it'd be a
direct to memory transfer though.

> Advantages of memory mapped port are: improved read performance,
> MEM_TO_MEM DMA support can be added (ti-qspi hardware as such does not
> provide DMA events).

DMA would definitely help here.

> I just need to know whether the user that requested the transfer is
> m25p80 driver. If yes, ti-qspi driver can take advantage of memory
> mapped interface, else just use config port to access SPI bus directly.

You don't *really* care if it's that specific user so much as that it's
that particular pattern.

> Writing separate driver based on spi-nor framework to interface with
> m25p80 is not an option because, I would lose the ability to interface
> with non-flash devices.

You could, however, expose an explicit flash mapping interface for this
functionality.  That does seem like it's going to be an awful lot easier 
and help with keeping things like DMA support out of the driver and in
the core (which would be useful if there's other controllers with the
same functionality, I seem to recall that there are).

> The spi_message that is received in transfer_one_message() is too
> generic to imply the slave device that is on the other side of the wire.
> IMO, the read command does not imply that the slave is m25p80 flash
> (besides the read opcodes vary across vendors of m25p80 and across modes).

Again, it doesn't matter if it's actually a read command only that it's
got a compatible format on the bus.
Russell King - ARM Linux Aug. 6, 2015, 9:33 p.m. UTC | #26
On Thu, Aug 06, 2015 at 06:14:00PM +0200, Geert Uytterhoeven wrote:
> On Thu, Aug 6, 2015 at 3:51 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Thu, Aug 06, 2015 at 05:55:23PM +0530, Vignesh R wrote:
> >> On the whole following are my requirements:
> >> 1. to be able to communicate with non -flash SPI devices via config port
> >> ( this functionality is supported by current driver, I dont want to
> >> break it). Or pump any spi_message on to SPI bus directly.
> >> 2. take advantage of memory mapped port in order to increase read
> >> throughput( and use dma in future) when the slave is a m25p80 type flash.
> >> 3. handle m25p80 as well as other slave on multiple chipselects.
> >>
> >> I just need to know whether the user that requested the transfer is
> >> m25p80 driver. If yes, ti-qspi driver can take advantage of memory
> >> mapped interface, else just use config port to access SPI bus directly.
> >
> > The problem with this approach is that it's an abomination.  It's adding
> > a SPI-user specific hack which is detected by a specific driver.  That's
> > really not sane - what happens when we have lots of these kinds of "I'm
> > an X SPI-user" with drivers detecting that?  It's not maintainable in the
> > long term.
> >
> > Yes, your requirements _today_ seem simple and easy, but you're only
> > thinking about today, not tomorrow when you've moved on and someone else
> > has to maintain the mess left behind (or delete it from mainline because
> > they're sick of dealing with a hack.)
> >
> >> The spi_message that is received in transfer_one_message() is too
> >> generic to imply the slave device that is on the other side of the wire.
> >> IMO, the read command does not imply that the slave is m25p80 flash
> >> (besides the read opcodes vary across vendors of m25p80 and across modes).
> >
> > I can see both sides of the argument.
> >
> > Mark is saying: if the SPI driver detects that the message to be transmitted
> > is a read command followed by the appropriate number of dummy bytes, and
> > then the data being read _and_ it's using quad-mode access, and the hardware
> > generates _exactly_ that in hardware using the memory mapped mode, there is
> > no reason _not_ to use the hardware to achieve that SPI transaction.  The
> > bus activity will be identical to what happens when the SPI controller is
> > used manually to achieve that bus sequence.
> >
> > You're saying: but the documentation says you can't use it for anything
> > except m25p80.  If you look at 24.5.4.1.2, it tells you what the SFI
> > generates on the bus, which is:
> >
> > 1. CS active
> > 2. Read command byte sent
> > 3. 1-4 address bytes sent
> > 4. 0-3 dummy bytes sent
> > 5. data bytes read from bus
> > 6. CS inactive
> >
> > So, Mark's point is "if we can detect a transaction which fits _that_
> > bus activity, there's no reason not to use this acceleration for the
> > transaction."
> >
> > What you're failing to counter with is: we don't have enough information
> > in the SPI driver to know how many dummy bytes there are between the
> > address bytes and the data read from the bus.
> 
> Irrespective of the dummy bytes.
> What if the spi device is not a FLASH ROM, but some other device,
> which receives a data packet that accidentally looks like an m25p80 READ
> command?

Well, for the most part it looks like it should still work, but there
could be a gotcha, but first, let's get rid of a myth there.

The QSPI is _not_ specific to the M25P80.  The manual says nothing
about being specific to that device.  What it says is that it's for
SPI NOR memory.  It will work with bus widths of 1, 2 or 4 data lines,
so it probably works with non-M25P80 SPI NOR devices too - and the fact
that the read and write commands are completely programmable suggests
that using it with SPI NOR devices which do not use the M25P80 read
command value is intended.


The SFI is a state machine based translator which sits behind the SPI
interface (look at the manual).  It sequence sthe SPI bus through a
series of standard SPI states which happen to be the states I detailed
above.

Now, the first byte of the SFI-generated SPI message can be programmed
to any 8 bit value.  So the first byte of the SPI message is totally
under software control.  The next one to four bytes which comprise the
"address" can be controlled to by deciding where in the memory map to
start reading from.  Hence, the value of those bytes is also totally
under software control.  The number of dummy bytes can be programmed
too.  So far so good.

So, if we know that we have a SPI message which says "send 0x01 0x20
0x30, send one dummy byte, read 32 bytes", if we program the SFI to
send a read command as 0x01, program an address length of 2 bytes
with one dummy byte, and then read the next 32 bytes at the appropriate
offset in the memory mapping to cause the next two bytes to be 0x20,
0x30, then what we end up with on the bus is:

	send 0x01, 0x20, 0x30
	send one dummy byte

That much is good, but now is the problem - how does the SFI know that
we're going to require to read 32 bytes?  I think the answer to that
is that it doesn't know, so it probably just reads the number of bytes
which the access on the SoC bus is asking for, which makes it
indeterminant from a software point of view to control how many bytes
will be read without provoking another "send 0x01, next address, dummy
byte" sequence.

So, I'm now on the side of not parsing commands in the SPI driver, and
back on the idea that this needs to be handled in some other manner
which doesn't involve polluting the SPI core with flag-hacks.
Michal Suchanek Aug. 7, 2015, 7:38 a.m. UTC | #27
On 6 August 2015 at 23:33, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Aug 06, 2015 at 06:14:00PM +0200, Geert Uytterhoeven wrote:
>> On Thu, Aug 6, 2015 at 3:51 PM, Russell King - ARM Linux
>> <linux@arm.linux.org.uk> wrote:
>> > On Thu, Aug 06, 2015 at 05:55:23PM +0530, Vignesh R wrote:
>> >> On the whole following are my requirements:
>> >> 1. to be able to communicate with non -flash SPI devices via config port
>> >> ( this functionality is supported by current driver, I dont want to
>> >> break it). Or pump any spi_message on to SPI bus directly.
>> >> 2. take advantage of memory mapped port in order to increase read
>> >> throughput( and use dma in future) when the slave is a m25p80 type flash.
>> >> 3. handle m25p80 as well as other slave on multiple chipselects.
>> >>
>> >> I just need to know whether the user that requested the transfer is
>> >> m25p80 driver. If yes, ti-qspi driver can take advantage of memory
>> >> mapped interface, else just use config port to access SPI bus directly.
>> >
>> > The problem with this approach is that it's an abomination.  It's adding
>> > a SPI-user specific hack which is detected by a specific driver.  That's
>> > really not sane - what happens when we have lots of these kinds of "I'm
>> > an X SPI-user" with drivers detecting that?  It's not maintainable in the
>> > long term.
>> >
>> > Yes, your requirements _today_ seem simple and easy, but you're only
>> > thinking about today, not tomorrow when you've moved on and someone else
>> > has to maintain the mess left behind (or delete it from mainline because
>> > they're sick of dealing with a hack.)
>> >
>> >> The spi_message that is received in transfer_one_message() is too
>> >> generic to imply the slave device that is on the other side of the wire.
>> >> IMO, the read command does not imply that the slave is m25p80 flash
>> >> (besides the read opcodes vary across vendors of m25p80 and across modes).
>> >
>> > I can see both sides of the argument.
>> >
>> > Mark is saying: if the SPI driver detects that the message to be transmitted
>> > is a read command followed by the appropriate number of dummy bytes, and
>> > then the data being read _and_ it's using quad-mode access, and the hardware
>> > generates _exactly_ that in hardware using the memory mapped mode, there is
>> > no reason _not_ to use the hardware to achieve that SPI transaction.  The
>> > bus activity will be identical to what happens when the SPI controller is
>> > used manually to achieve that bus sequence.
>> >
>> > You're saying: but the documentation says you can't use it for anything
>> > except m25p80.  If you look at 24.5.4.1.2, it tells you what the SFI
>> > generates on the bus, which is:
>> >
>> > 1. CS active
>> > 2. Read command byte sent
>> > 3. 1-4 address bytes sent
>> > 4. 0-3 dummy bytes sent
>> > 5. data bytes read from bus
>> > 6. CS inactive
>> >
>> > So, Mark's point is "if we can detect a transaction which fits _that_
>> > bus activity, there's no reason not to use this acceleration for the
>> > transaction."
>> >
>> > What you're failing to counter with is: we don't have enough information
>> > in the SPI driver to know how many dummy bytes there are between the
>> > address bytes and the data read from the bus.
>>
>> Irrespective of the dummy bytes.
>> What if the spi device is not a FLASH ROM, but some other device,
>> which receives a data packet that accidentally looks like an m25p80 READ
>> command?
>
> Well, for the most part it looks like it should still work, but there
> could be a gotcha, but first, let's get rid of a myth there.
>
> The QSPI is _not_ specific to the M25P80.  The manual says nothing
> about being specific to that device.  What it says is that it's for
> SPI NOR memory.  It will work with bus widths of 1, 2 or 4 data lines,
> so it probably works with non-M25P80 SPI NOR devices too - and the fact
> that the read and write commands are completely programmable suggests
> that using it with SPI NOR devices which do not use the M25P80 read
> command value is intended.
>
...
>
> That much is good, but now is the problem - how does the SFI know that
> we're going to require to read 32 bytes?  I think the answer to that
> is that it doesn't know, so it probably just reads the number of bytes
> which the access on the SoC bus is asking for, which makes it
> indeterminant from a software point of view to control how many bytes
> will be read without provoking another "send 0x01, next address, dummy
> byte" sequence.
>
> So, I'm now on the side of not parsing commands in the SPI driver, and
> back on the idea that this needs to be handled in some other manner
> which doesn't involve polluting the SPI core with flag-hacks.

OK, so we can agree that using this hardware acceleration for any kind
of transfer indiscriminately is not a very good idea.

Now since the description is clearer it's obvious that ti-qspi cannot
work fully mmapped as fsl-qspi does because the setup has to be done
over normal spi access and using non-m25p80 devices on the same bus is
a requirement.

The place where it is known if a transfer can use the mmap access is m25p80.c

So my suggestion is

 - add a new method for spi master that gets the read opcode, dummy
length, address, address length, buffer, buffer length and performs
read from the flash memory in a hardware-specific way

- add a check in m25p80.c that the master supports this feature and if
so use it (eg check that the method is non-null)

Presumably if some new SPI controllers with similar feature are
supported in the future they can use the same inteface because you
pass on everything the m25p80 read knows.

Thanks

Michal
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Martin Sperl Aug. 7, 2015, 8:25 a.m. UTC | #28
On 8/6/2015 23:33, Russell King - ARM Linux wrote:
> On Thu, Aug 06, 2015 at 06:14:00PM +0200, Geert Uytterhoeven wrote:
>>
>> Irrespective of the dummy bytes.
>> What if the spi device is not a FLASH ROM, but some other device,
>> which receives a data packet that accidentally looks like an m25p80 READ
>> command?
> Well, for the most part it looks like it should still work, but there
> could be a gotcha, but first, let's get rid of a myth there.
>
> The QSPI is _not_ specific to the M25P80.  The manual says nothing
> about being specific to that device.  What it says is that it's for
> SPI NOR memory.  It will work with bus widths of 1, 2 or 4 data lines,
> so it probably works with non-M25P80 SPI NOR devices too - and the fact
> that the read and write commands are completely programmable suggests
> that using it with SPI NOR devices which do not use the M25P80 read
> command value is intended.
>
>
> The SFI is a state machine based translator which sits behind the SPI
> interface (look at the manual).  It sequence sthe SPI bus through a
> series of standard SPI states which happen to be the states I detailed
> above.
>
> Now, the first byte of the SFI-generated SPI message can be programmed
> to any 8 bit value.  So the first byte of the SPI message is totally
> under software control.  The next one to four bytes which comprise the
> "address" can be controlled to by deciding where in the memory map to
> start reading from.  Hence, the value of those bytes is also totally
> under software control.  The number of dummy bytes can be programmed
> too.  So far so good.
>
> So, if we know that we have a SPI message which says "send 0x01 0x20
> 0x30, send one dummy byte, read 32 bytes", if we program the SFI to
> send a read command as 0x01, program an address length of 2 bytes
> with one dummy byte, and then read the next 32 bytes at the appropriate
> offset in the memory mapping to cause the next two bytes to be 0x20,
> 0x30, then what we end up with on the bus is:
>
> 	send 0x01, 0x20, 0x30
> 	send one dummy byte
>
> That much is good, but now is the problem - how does the SFI know that
> we're going to require to read 32 bytes?  I think the answer to that
> is that it doesn't know, so it probably just reads the number of bytes
> which the access on the SoC bus is asking for, which makes it
> indeterminant from a software point of view to control how many bytes
> will be read without provoking another "send 0x01, next address, dummy
> byte" sequence.
>
> So, I'm now on the side of not parsing commands in the SPI driver, and
> back on the idea that this needs to be handled in some other manner
> which doesn't involve polluting the SPI core with flag-hacks.
>
So I see 2 distinct options:

Have the nor driver modified to run SPI commands and then ask the
SPI framework (and driver) to switch into mmap mode:

Would probably look something like this inside the nor driver:
    /* lock spi bus for other activities */
    spi_bus_lock(spi);
    /* send the "configuration" for mmap */
    t[0].tx_buf = flash->command;
    t[0].len = m25p_cmdsz(nor);
    spi_message_add_tail(&t[0], &m);
    t[1].tx_buf = dummy_buffer;
    t[1].len = dummy;
    spi_message_add_tail(&t[1], &m);
    spi_sync(spi, &m);
    /* switch to mmap mode */
    spi->mode |= SPI_MMAP;
    spi_setup(spi);
    /* run the mmapped transfers bypassing the spi-layer */
    memcpy(...)
    /* open questions here: which address range
     * and how to detect if transfer is done
*/
/* restore back to "normal" mode */
    spi->mode &= ~SPI_MMAP;
    spi_setup(spi);
    /* unlock spi bus for other activities */
    spi_bus_unlock(spi);

The downside is that it requires modification in several places
(nor-framework, spi-framework plus the driver) and it would not
be generic enough...

IMO such a situation is feasible if we only got a single device
on the spi-bus, but leaves a lot of questions open...
Alternatively we could create an additional api.

On the other end of spectrum could be a solution where the
spi-master driverwould have the opportunity to query the
device-tree for specific propertiesduring the spi_add_device
phase - in this case querying the followingproperty in the
device-tree:
   spi-master-XXX,use-mmap-cmd-mode = <0x08 0x38>;
to implement mmap-mode for commands 0x08 and 0x38.

Maybe we would want to also encode the number of address bytes
to send per command without hardcoding those values explicitly:
so maybe something like:
   spi-master-XXX,use-mmap-cmd-mode = <0x08 2> <0x38 3>;

Obviously these would need to get documented in the bindings
documentation of that driver.

Alternatively we could also introduce generic alternate modes
for the driver(similar to GPIO - ALT modes), but that would be
less transparent and more hard-coded...

In the end this would mean that from the nor framework side
therewould be no change at all - it still would be issuing
something like this:
    /* send the "normal" block read command */
    t[0].tx_buf = flash->command;
    /* note that the address would be encoded here */
    t[0].len = m25p_cmdsz(nor);
    spi_message_add_tail(&t[0], &m);
    /* dummy bytes could also get added to the above transfer */
    t[1].tx_buf = dummy_buffer;
    t[1].len = dummy;
    spi_message_add_tail(&t[1], &m);
    /* the real transfer */
    t[2].rx_buf = read_buffer;
    t[2].len = transfer_size;
    spi_message_add_tail(&t[2], &m);
    spi_sync(spi, &m);

On the spi-master side the driver would need to run:
*  if the spi-message (in this case the first byte) matches
    the "allowed" command pattern:
   * "setup" device in normal mode preparing the transfer engine
   * mode-switch to "mmapped" mode
   * copy via mmapped mode (via DMA to avoid blocking the CPU?)
   * return to "normal" mode
* else
   * run in "normal" spi mode.
(obviously it would be a bit more complicated that that).

Note that a discussion in regards to spi-master methods called
duringspi_add_device has just come up a few days ago in a
slightly differentcontext - forcing to always/never use DMA mode
for a specific spi-device on the bus (as well as tuning other
parameters per device).

Obviously the additional properties should describe required
HW behaviour and not tune the driver parameters - sys should be
used for those, but also for implementing those sys parameters we
would need those above "hooks"...

Just an idea.

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vignesh Raghavendra Aug. 7, 2015, 8:35 a.m. UTC | #29
On 08/07/2015 01:08 PM, Michal Suchanek wrote:

> Now since the description is clearer it's obvious that ti-qspi cannot
> work fully mmapped as fsl-qspi does because the setup has to be done
> over normal spi access and using non-m25p80 devices on the same bus is
> a requirement.
> 
> The place where it is known if a transfer can use the mmap access is m25p80.c
> 
> So my suggestion is
> 
>  - add a new method for spi master that gets the read opcode, dummy
> length, address, address length, buffer, buffer length and performs
> read from the flash memory in a hardware-specific way
> 
> - add a check in m25p80.c that the master supports this feature and if
> so use it (eg check that the method is non-null)
> 
> Presumably if some new SPI controllers with similar feature are
> supported in the future they can use the same inteface because you
> pass on everything the m25p80 read knows.
> 

Ok... Do you mean something like this?

I will take m25p80 as example but can be expanded for any flash.

In include/linux/mtd.h:
	struct spi_mtd_config_info {
		struct spi_device 	*spi;
	        u32                     page_size;
	        u8                      addr_width;
       		u8                      erase_opcode;
	        u8                      read_opcode;
        	u8                      read_dummy;
	        u8                      program_opcode;
        	enum read_mode          flash_read;

	} /* subset of struct spi_nor */


In m25p80.c:

	static int m25p80_read(struct spi_nor *nor, loff_t from,
				size_t len, size_t *retlen,
				u_char *buf)
	{
		struct spi_mtd_config_info info;
		struct spi_device *spi;
		
		if (spi->master->spi_mtd_mmap_read) {
		  /* Populate spi_mtd_config_info */
		  spi->master->spi_mtd_mmap_read(&info, from, len,
						 retlen, buf);
		}
		else {
		/* no mtd specific acceleration supported try normal
		 * SPI way of communicating with flash
		 * continue with current code
		 * set up spi_message and call spi_sync()
		 */
	}

      }

In spi-ti-qspi.c:
Implement spi_mtd_mmap_read while holding master->bus_lock mutex.
Michal Suchanek Aug. 7, 2015, 10:16 a.m. UTC | #30
On 7 August 2015 at 10:25, Martin Sperl <martin@sperl.org> wrote:
> On 8/6/2015 23:33, Russell King - ARM Linux wrote:
>>
>> On Thu, Aug 06, 2015 at 06:14:00PM +0200, Geert Uytterhoeven wrote:
>>>
>>>
>>> Irrespective of the dummy bytes.
>>> What if the spi device is not a FLASH ROM, but some other device,
>>> which receives a data packet that accidentally looks like an m25p80 READ
>>> command?
>>
>> Well, for the most part it looks like it should still work, but there
>> could be a gotcha, but first, let's get rid of a myth there.
>>
>> The QSPI is _not_ specific to the M25P80.  The manual says nothing
>> about being specific to that device.  What it says is that it's for
>> SPI NOR memory.  It will work with bus widths of 1, 2 or 4 data lines,
>> so it probably works with non-M25P80 SPI NOR devices too - and the fact
>> that the read and write commands are completely programmable suggests
>> that using it with SPI NOR devices which do not use the M25P80 read
>> command value is intended.
>>
>>
>> The SFI is a state machine based translator which sits behind the SPI
>> interface (look at the manual).  It sequence sthe SPI bus through a
>> series of standard SPI states which happen to be the states I detailed
>> above.
>>
>> Now, the first byte of the SFI-generated SPI message can be programmed
>> to any 8 bit value.  So the first byte of the SPI message is totally
>> under software control.  The next one to four bytes which comprise the
>> "address" can be controlled to by deciding where in the memory map to
>> start reading from.  Hence, the value of those bytes is also totally
>> under software control.  The number of dummy bytes can be programmed
>> too.  So far so good.
>>
>> So, if we know that we have a SPI message which says "send 0x01 0x20
>> 0x30, send one dummy byte, read 32 bytes", if we program the SFI to
>> send a read command as 0x01, program an address length of 2 bytes
>> with one dummy byte, and then read the next 32 bytes at the appropriate
>> offset in the memory mapping to cause the next two bytes to be 0x20,
>> 0x30, then what we end up with on the bus is:
>>
>>         send 0x01, 0x20, 0x30
>>         send one dummy byte
>>
>> That much is good, but now is the problem - how does the SFI know that
>> we're going to require to read 32 bytes?  I think the answer to that
>> is that it doesn't know, so it probably just reads the number of bytes
>> which the access on the SoC bus is asking for, which makes it
>> indeterminant from a software point of view to control how many bytes
>> will be read without provoking another "send 0x01, next address, dummy
>> byte" sequence.
>>
>> So, I'm now on the side of not parsing commands in the SPI driver, and
>> back on the idea that this needs to be handled in some other manner
>> which doesn't involve polluting the SPI core with flag-hacks.
>>
> So I see 2 distinct options:
>
> Have the nor driver modified to run SPI commands and then ask the
> SPI framework (and driver) to switch into mmap mode:
>
> Would probably look something like this inside the nor driver:
>    /* lock spi bus for other activities */
>    spi_bus_lock(spi);
>    /* send the "configuration" for mmap */
>    t[0].tx_buf = flash->command;
>    t[0].len = m25p_cmdsz(nor);
>    spi_message_add_tail(&t[0], &m);
>    t[1].tx_buf = dummy_buffer;
>    t[1].len = dummy;
>    spi_message_add_tail(&t[1], &m);
>    spi_sync(spi, &m);

>    /* switch to mmap mode */
>    spi->mode |= SPI_MMAP;

Presumably you will do this *before* sending the read command so the
SPI driver can reverse-engineer it according to the spi-nor read
pattern.

Then the mmap mode can be set in spi_sync() but you also have to lock
the spi controller to prevent other transfers from resetting it.

Or you can pass the read buffer to the SPI master driver as well to do
the memcpy for you. Which you want to do anyway in case the SPI master
can use DMA to fill the buffer rather than memcpy.

>    spi_setup(spi);
>    /* run the mmapped transfers bypassing the spi-layer */
>    memcpy(...)
>    /* open questions here: which address range
>     * and how to detect if transfer is done
> */

Presumably when the memcpy ends the transfer is done.

> /* restore back to "normal" mode */
>    spi->mode &= ~SPI_MMAP;
>    spi_setup(spi);
>    /* unlock spi bus for other activities */
>    spi_bus_unlock(spi);

Presumably you have to restore to non-mmap mode only when you receive
a command that requires it. If the next command is read with same
configuration you can just keep reading.

>
> The downside is that it requires modification in several places
> (nor-framework, spi-framework plus the driver) and it would not
> be generic enough...

You only need modification to the SPI master driver and m25p80 driver.

The SPI master driver is where the hardware-specific operation is
executed and m25p80 is where you have the information so you can
decide to take advantage of the hardware acceleration.

>
> IMO such a situation is feasible if we only got a single device
> on the spi-bus, but leaves a lot of questions open...
> Alternatively we could create an additional api.

The spi master driver can track what mode is set on the controller and
change it as needed before each transfer. This is what is commonly
done for other SPI master hardware configuration options.

>
> On the other end of spectrum could be a solution where the
> spi-master driverwould have the opportunity to query the
> device-tree for specific propertiesduring the spi_add_device
> phase - in this case querying the followingproperty in the
> device-tree:
>   spi-master-XXX,use-mmap-cmd-mode = <0x08 0x38>;
> to implement mmap-mode for commands 0x08 and 0x38.

This is bogus.

Firstly this is per-slave and not per-master.

Secondly in devicetree you have jedec,spi-nor which says exactly that
the SPI slave is a device that responds to the JEDEC identify command.
Nothing more. The data returned from the identify command is used to
determine what the command opcodes are, what features are supported,
etc. So that is *not* in the dt and there is no place for hardwiring
opcodes in the dt.

> Alternatively we could also introduce generic alternate modes
> for the driver(similar to GPIO - ALT modes), but that would be
> less transparent and more hard-coded...
>
> In the end this would mean that from the nor framework side
> therewould be no change at all - it still would be issuing
> something like this:
>    /* send the "normal" block read command */
>    t[0].tx_buf = flash->command;
>    /* note that the address would be encoded here */
>    t[0].len = m25p_cmdsz(nor);
>    spi_message_add_tail(&t[0], &m);
>    /* dummy bytes could also get added to the above transfer */
>    t[1].tx_buf = dummy_buffer;
>    t[1].len = dummy;
>    spi_message_add_tail(&t[1], &m);
>    /* the real transfer */
>    t[2].rx_buf = read_buffer;
>    t[2].len = transfer_size;
>    spi_message_add_tail(&t[2], &m);
>    spi_sync(spi, &m);
>
> On the spi-master side the driver would need to run:
> *  if the spi-message (in this case the first byte) matches
>    the "allowed" command pattern:

There is no 'allowed' pattern. Any message like 1~7 bytes long can be
interpreted as read command. Unless you can tell the SPI master driver
it cannot know.

And you go the abominable route of the original patch that you compose
a SPI message in m25p80, and then decide in the SPI master driver that
you will in fact not send a SPI message and reverse-engineer what
m25p80 really meant.

On 7 August 2015 at 10:35, Vignesh R <vigneshr@ti.com> wrote:
>
>
> On 08/07/2015 01:08 PM, Michal Suchanek wrote:
>
>> Now since the description is clearer it's obvious that ti-qspi cannot
>> work fully mmapped as fsl-qspi does because the setup has to be done
>> over normal spi access and using non-m25p80 devices on the same bus is
>> a requirement.
>>
>> The place where it is known if a transfer can use the mmap access is m25p80.c
>>
>> So my suggestion is
>>
>>  - add a new method for spi master that gets the read opcode, dummy
>> length, address, address length, buffer, buffer length and performs
>> read from the flash memory in a hardware-specific way
>>
>> - add a check in m25p80.c that the master supports this feature and if
>> so use it (eg check that the method is non-null)
>>
>> Presumably if some new SPI controllers with similar feature are
>> supported in the future they can use the same inteface because you
>> pass on everything the m25p80 read knows.
>>
>
> Ok... Do you mean something like this?
>
> I will take m25p80 as example but can be expanded for any flash.
>
> In include/linux/mtd.h:
>         struct spi_mtd_config_info {
>                 struct spi_device       *spi;
>                 u32                     page_size;
>                 u8                      addr_width;
>                 u8                      erase_opcode;
>                 u8                      read_opcode;
>                 u8                      read_dummy;
>                 u8                      program_opcode;
>                 enum read_mode          flash_read;
>
>         } /* subset of struct spi_nor */
>

I would just pass these as separate arguments to the function but whatver.

> In m25p80.c:
>
>         static int m25p80_read(struct spi_nor *nor, loff_t from,
>                                 size_t len, size_t *retlen,
>                                 u_char *buf)
>         {
>                 struct spi_mtd_config_info info;
>                 struct spi_device *spi;
>
>                 if (spi->master->spi_mtd_mmap_read) {
>                   /* Populate spi_mtd_config_info */
>                   spi->master->spi_mtd_mmap_read(&info, from, len,
>                                                  retlen, buf);
>                 }
>                 else {
>                 /* no mtd specific acceleration supported try normal
>                  * SPI way of communicating with flash
>                  * continue with current code
>                  * set up spi_message and call spi_sync()
>                  */
>         }
>
>       }
>
> In spi-ti-qspi.c:
> Implement spi_mtd_mmap_read while holding master->bus_lock mutex.
>

Thanks

Michal
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vignesh Raghavendra Aug. 12, 2015, 9:27 a.m. UTC | #31
On 08/07/2015 03:46 PM, Michal Suchanek wrote:
[snip]
> On 7 August 2015 at 10:35, Vignesh R <vigneshr@ti.com> wrote:
>>
>>
>> On 08/07/2015 01:08 PM, Michal Suchanek wrote:
>>
>>> Now since the description is clearer it's obvious that ti-qspi cannot
>>> work fully mmapped as fsl-qspi does because the setup has to be done
>>> over normal spi access and using non-m25p80 devices on the same bus is
>>> a requirement.
>>>
>>> The place where it is known if a transfer can use the mmap access is m25p80.c
>>>
>>> So my suggestion is
>>>
>>>  - add a new method for spi master that gets the read opcode, dummy
>>> length, address, address length, buffer, buffer length and performs
>>> read from the flash memory in a hardware-specific way
>>>
>>> - add a check in m25p80.c that the master supports this feature and if
>>> so use it (eg check that the method is non-null)
>>>
>>> Presumably if some new SPI controllers with similar feature are
>>> supported in the future they can use the same inteface because you
>>> pass on everything the m25p80 read knows.
>>>
>>
>> Ok... Do you mean something like this?
>>
>> I will take m25p80 as example but can be expanded for any flash.
>>
>> In include/linux/mtd.h:
>>         struct spi_mtd_config_info {
>>                 struct spi_device       *spi;
>>                 u32                     page_size;
>>                 u8                      addr_width;
>>                 u8                      erase_opcode;
>>                 u8                      read_opcode;
>>                 u8                      read_dummy;
>>                 u8                      program_opcode;
>>                 enum read_mode          flash_read;
>>
>>         } /* subset of struct spi_nor */
>>
> 
> I would just pass these as separate arguments to the function but whatver.
> 
>> In m25p80.c:
>>
>>         static int m25p80_read(struct spi_nor *nor, loff_t from,
>>                                 size_t len, size_t *retlen,
>>                                 u_char *buf)
>>         {
>>                 struct spi_mtd_config_info info;
>>                 struct spi_device *spi;
>>
>>                 if (spi->master->spi_mtd_mmap_read) {
>>                   /* Populate spi_mtd_config_info */
>>                   spi->master->spi_mtd_mmap_read(&info, from, len,
>>                                                  retlen, buf);
>>                 }
>>                 else {
>>                 /* no mtd specific acceleration supported try normal
>>                  * SPI way of communicating with flash
>>                  * continue with current code
>>                  * set up spi_message and call spi_sync()
>>                  */
>>         }
>>
>>       }
>>
>> In spi-ti-qspi.c:
>> Implement spi_mtd_mmap_read while holding master->bus_lock mutex.
>>
> 

I will re-submit patches based on the above idea, if there are no
further comments..
diff mbox

Patch

diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index d673072346f2..f1a0329ee63f 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -640,6 +640,8 @@  struct spi_transfer {
  * @actual_length: the total number of bytes that were transferred in all
  *	successful segments
  * @status: zero for success, else negative errno
+ * @use_mmap_mode: Indicate to spi master to perform memory mapped
+ *	read if possible.
  * @queue: for use by whichever driver currently owns the message
  * @state: for use by whichever driver currently owns the message
  *
@@ -681,6 +683,7 @@  struct spi_message {
 	unsigned		frame_length;
 	unsigned		actual_length;
 	int			status;
+	bool			use_mmap_mode;
 
 	/* for optional use by whatever driver currently owns the
 	 * spi_message ...  between calls to spi_async and then later