Re: [PATCH linux-next 1/5] mtd: spi-nor: properly detect the memory when it boots in Quad or Dual mode

2016-01-04 Thread Cyrille Pitchen
Hi Brian,

Le 18/12/2015 02:55, Brian Norris a écrit :
> Hi Cyrille,
> 
> On Mon, Dec 07, 2015 at 03:09:10PM +0100, Cyrille Pitchen wrote:
[...]
>> +
>> +/* Set this protocol for all commands. */
>> +nor->reg_proto = configs[i].proto;
>> +nor->read_proto = configs[i].proto;
>> +nor->write_proto = configs[i].proto;
>> +nor->erase_proto = configs[i].proto;
> 
> Are these all fully independent? Do we really need 4 fields for this?
> 

Currently, for sure reg_proto and read_proto are independent. Let's take
Spansion memories as an example:
- Fast Read Quad Data 0x6B uses SPI 1-1-4
- register accesses (read/write) use SPI 1-1-1

AFAIK, Quad IO write commands are not used yet but if one day they are, for
instance with Macronix memories (QPI mode disabled):
- 4x I/O Page Program 0x38 uses SPI 1-1-4
- register accesses (read/write) uses SPI 1-1-1
- Fast Read Quad I/O 0xEB uses SPI 1-4-4
- Sector Erase 0x20 uses SPI 1-1-1

For now, I don't have any example where erase_proto is different from
reg_proto but for clarity reasons I'd rather keep erase_proto and reg_proto
distinct. Otherwise both field should be renamed as it looks odd to use
reg_proto when implementing the nor->erase() hook, doesn't it?

The names were chosen according to both the *_opcode and hooks from the
struct spi_nor:

hook   op code  protocol
read_reg() N/A  reg_proto
write_reg()N/A  reg_proto
read() read_opcode  read_proto
write()program_opcode   write_proto
erase()erase_opcode erase_proto

I admit following this logic 'program_opcode' should be renamed
'write_opcode'.



[...]
>> diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
>> index fac3f6f53981..c91986a99caf 100644
>> --- a/include/linux/mtd/spi-nor.h
>> +++ b/include/linux/mtd/spi-nor.h
>> @@ -75,8 +75,9 @@
>>  #define SPINOR_OP_BRWR  0x17/* Bank register write */
>>  
>>  /* Used for Micron flashes only. */
>> -#define SPINOR_OP_RD_EVCR  0x65/* Read EVCR register */
>> -#define SPINOR_OP_WD_EVCR  0x61/* Write EVCR register */
>> +#define SPINOR_OP_MIO_RDID  0xaf/* Multiple I/O Read JEDEC ID */
>> +#define SPINOR_OP_RD_EVCR   0x65/* Read EVCR register */
>> +#define SPINOR_OP_WD_EVCR   0x61/* Write EVCR register */
>>  
>>  /* Status Register bits. */
>>  #define SR_WIP  BIT(0)  /* Write in progress */
>> @@ -105,6 +106,16 @@ enum read_mode {
>>  SPI_NOR_QUAD,
>>  };
>>  
>> +enum spi_protocol {
>> +SPI_PROTO_1_1_1,/* SPI */
>> +SPI_PROTO_1_1_2,/* Dual Output */
>> +SPI_PROTO_1_1_4,/* Quad Output */
>> +SPI_PROTO_1_2_2,/* Dual IO */
>> +SPI_PROTO_1_4_4,/* Quad IO */
>> +SPI_PROTO_2_2_2,/* Dual Command */
>> +SPI_PROTO_4_4_4,/* Quad Command */
> 
> Would it help at all to make this enum into something more like a
> bitfield? So in some cases, rather than a bit switch block, we can just
> extract the "number of lines" from the integer value? e.g.:
> 
> #define SNOR_PROTO(command, addr, data) \
>   (((command) << 0) | \
>((addr) << 4) | \
>((data) << 8)) // or some other kind of macro magic
> 
> enum spi_nor_protocol {
>   SNOR_PROTO_1_1_1= SNOR_PROTO(1, 1, 1),
>   SNOR_PROTO_1_1_2= SNOR_PROTO(1, 1, 2),
>   ...
> };
> 
> static inline int spi_nor_io_lines_command(enum spi_nor_protocol proto)
> {
>   return proto & 0xf;
> }
> 
> (Similar for addr and data phases. Also, my naming might suck. Feel free
> to improve!)
> 
> I don't think we should stomp on the SPI namespace with the
> "SPI_PROTO_*" definitions. That's why I chose SNOR_PROTO_ and spi_nor_
> prefixes.
> 

It looks good to me so I'll change for that :)

> Brian


Best regards,

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


Re: [PATCH linux-next 2/5] mtd: spi-nor: fix Quad SPI mode support for Spansion, Micron and Macronix

2016-01-04 Thread Cyrille Pitchen
Hi Brian,

Le 18/12/2015 03:18, Brian Norris a écrit :
> On Mon, Dec 07, 2015 at 03:09:11PM +0100, Cyrille Pitchen wrote:
>> This patch reworks the support of Quad and Dual SPI protocols for Micron,
>> Spansion and Macronix Quad/Dual capable memories. Indeed, in the best
>> case, only Spansion memories are correctly supported by the current
>> spi-nor framework.
> 
> ^^ Ah, so this is what I was struggling with at first. I agree that
> Micron looks broken. Quite possibly Macronix too. Unfortunately, I
> haven't had great test hardware for some of the quad modes. Especially
> not anything that supports generic SPI, and not completely on mainline.
> 

To explain the origin of this series of patches I would say that at first
I was only supposed to write a driver for the Atmel QSPI controller. I was
using (ans still use) a sama5d2 xplained board with a Micron n25q128a13
memory. Hence, testing the driver, I found that the probe failed inside the
old micron_quad_enable() function.
Indeed nor->write_reg() was successfully called to clear the Quad Enable bit
in the Enhanced Volatile Configuration Register but immediately after
spi_nor_wait_till_ready() failed.
The reason was that the Micron memory was switched to its Quad Mode and then
expected all the following commands to use the SPI 4-4-4 protocol. However
the Atmel QSPI controller driver was not aware of this protocol change and
kept on using the SPI 1-1-1 protocol.

So in the very first version of this series of patches, I inserted a call of
spi_nor_set_protocol(), a new function simply calling an optional hook,
between the nor->write_reg() and spi_nor_wait_till_ready() calls. This way
the (Q)SPI controller driver was now notified about the protocol switch and
can eventually adapt to this change.

After some discussions on the mailing list, it appeared that using such a
hook to handle protocol changes would required to insert calls of the new
spi_nor_set_protocol() function before all the calls of nor->read_reg(),
nor->write_reg(), nor->read(), nor->write() and nor->erase().
Indeed some manufacturers like Spansion use different numbers of I/O lines
depending on the type of operation:
- Fast Read: 1-1-4
- register read/write: 1-1-1

So the addition inside struct spi_nor of the new reg_proto, read_proto,
write_proto and erase_proto fields was prefered to the first
spi_nor_set_protocol() proposal. This fields are set once for all by
spi_nor_scan(). SPI controller drivers have to worry about their values only
if they claim to support Dual or Quad protocols through the 'mode' argument
of spi_nor_scan().

Then about the Micron case, I did test it and it didn't work without patching.
To be cautious, I wondered whether it might have work with a
different configuration/SPI controller because I don't want to break
something working. I wondered about a mean for the SPI controller driver to
detect the protocol change. Maybe parsing the SPI message and checking the
command op code. However it looked a highly inefficient method and also it
simply can not work since the very same op code, for instance 0x6B, is used
by both the 1-1-4 and 4-4-4 protocols.
So my conclusion was it could not have worked before: I don't have to worry
about breaking the support of Quad protocols for Micron memories.

I don't think there is a real need to revert Bean's commit since this series
fixes the issue anyway. However if you feel it would be better to revert it to
start from a cleaner base, I'm fine with it. Just let me know your choice so
I can adapt my series before sending the next version.


About the Macronix case, I still don't have any memory sample to test.
However, reading some memory datasheet (again and again), my understanding
has changed a little bit: setting the Quad Enable (QE) non-volatile bit in
the Status Register doesn't mean enabling the Quad Peripheral Interface (QPI)
as I thought.
Two dedicated op codes are used when sending the required commands to
enable/disable the QPI. Once the QPI enabled, the memory expects ALL commands
to use the SPI 4-4-4 protocol. Enabling the QPI requires the QE bit to bit set
first in the Status Register.
However the QE bit is also required to use the SPI 1-1-4 protocol: QPI must be
disabled in that case.
Setting the QE bit only disables the Write Protect and Hold features: the two
associated pins then become the IO2 and IO3 lines, needed by Quad SPI
protocols.

Finally for the Winbond case, I don't have memory from this manufacturer
yet so once again I refer only to some datasheets: it looks like Winbond
memories use a pattern of behaviour very closed to Macronix' one.
Indeed, some Quad Enable non volatile bit must be set inside the Status
Register. Also two dedicated op codes are used to enable/disable the QPI mode.
The QPI mode requires the QE bit to be set and, once enabled, all commands
must use the SPI 4-4-4 protocol.
However the two op codes to enter/leave the QPI mod

Re: [PATCH linux-next 1/5] mtd: spi-nor: properly detect the memory when it boots in Quad or Dual mode

2015-12-18 Thread Cyrille Pitchen
Hi Brian,

I will be on vacation till 2016 January, 4th.
I will try to answer your questions as soon as possible.

Best regards,

Cyrille

Le 18/12/2015 02:55, Brian Norris a écrit :
> Hi Cyrille,
> 
> On Mon, Dec 07, 2015 at 03:09:10PM +0100, Cyrille Pitchen wrote:
>> The quad (or dual) mode of a spi-nor memory may be enabled at boot time by
>> non-volatile bits in some setting register. Also such a mode may have
>> already been enabled at early stage by some boot loader.
>>
>> Hence, we should not guess the spi-nor memory is always configured for the
>> regular SPI 1-1-1 protocol.
>>
>> Micron and Macronix memories, once their Quad (or dual for Micron) mode
>> enabled, no longer process the regular JEDEC Read ID (0x9f) command but
>> instead reply to a new command: JEDEC Read ID Multiple I/O (0xaf).
>> Besides, in Quad mode both memory manufacturers expect ALL commands to
>> use the SPI 4-4-4 protocol. For Micron memories, enabling their Dual mode
>> implies to use the SPI 2-2-2 protocol for ALL commands.
>>
>> Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
>> ---
>>  drivers/mtd/spi-nor/spi-nor.c | 52 
>> +++
>>  include/linux/mtd/spi-nor.h   | 23 +--
>>  2 files changed, 69 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
>> index 3b2460efc019..bf17736750c1 100644
>> --- a/drivers/mtd/spi-nor/spi-nor.c
>> +++ b/drivers/mtd/spi-nor/spi-nor.c
>> @@ -73,6 +73,11 @@ struct flash_info {
>>  
>>  #define JEDEC_MFR(info) ((info)->id[0])
>>  
>> +struct read_id_config {
>> +enum read_mode  mode;
>> +enum spi_protocol   proto;
>> +};
>> +
>>  static const struct flash_info *spi_nor_match_id(const char *name);
>>  
>>  /*
>> @@ -867,11 +872,16 @@ static const struct flash_info spi_nor_ids[] = {
>>  { },
>>  };
>>  
>> -static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
>> +static const struct flash_info *spi_nor_read_id(struct spi_nor *nor,
>> +enum read_mode mode)
> 
> It's unclear what you're trying to do with the 'read_mode' enum now.
> (Admittedly it may not be clear in the current code either, given the
> confusion we already have over Micron support.)
> 
> Would you care to document it better?
> 
>>  {
>> -int tmp;
>> +int i, tmp;
>>  u8  id[SPI_NOR_MAX_ID_LEN];
>>  const struct flash_info *info;
>> +static const struct read_id_config configs[] = {
>> +{SPI_NOR_QUAD, SPI_PROTO_4_4_4},
>> +{SPI_NOR_DUAL, SPI_PROTO_2_2_2}
>> +};
>>  
>>  tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
>>  if (tmp < 0) {
>> @@ -879,6 +889,34 @@ static const struct flash_info *spi_nor_read_id(struct 
>> spi_nor *nor)
>>  return ERR_PTR(tmp);
>>  }
>>  
>> +/* Special case for Micron/Macronix qspi nor. */
>> +if ((id[0] == 0xff && id[1] == 0xff && id[2] == 0xff) ||
>> +(id[0] == 0x00 && id[1] == 0x00 && id[2] == 0x00))
>> +for (i = 0; i < ARRAY_SIZE(configs); ++i) {
>> +if (configs[i].mode != mode)
>> +continue;
>> +
>> +/* Set this protocol for all commands. */
>> +nor->reg_proto = configs[i].proto;
>> +nor->read_proto = configs[i].proto;
>> +nor->write_proto = configs[i].proto;
>> +nor->erase_proto = configs[i].proto;
> 
> Are these all fully independent? Do we really need 4 fields for this?
> 
>> +
>> +/*
>> + * Multiple I/O Read ID only returns the Manufacturer ID
>> + * (1 byte) and the Device ID (2 bytes). So we reset the
>> + * remaining bytes.
>> + */
>> +memset(id, 0, sizeof(id));
>> +tmp = nor->read_reg(nor, SPINOR_OP_MIO_RDID, id, 3);
>> +if (tmp < 0) {
>> +dev_dbg(nor->dev,
>> +"error %d reading JEDEC ID Multi I/O\n",
>> +tmp);
>> +return ERR_PTR(tmp);
>> +

Re: [PATCH linux-next 0/5] mtd: spi-nor: add driver for Atmel QSPI controller

2015-12-08 Thread Cyrille Pitchen
Hi Brian,

Le 07/12/2015 20:34, Brian Norris a écrit :
> + Bean Huo
> 
> Hi Cyrille,
> 
> On Mon, Dec 07, 2015 at 03:09:09PM +0100, Cyrille Pitchen wrote:
>> Hi all,
>>
>> this series of patches adds support to the Atmel QSPI controller available
>> on sama5d2 SoCs. It was tested on a sama5d2 xplained ultra board with a 
>> Micron n25q128a13 QSPI memory and a at25df321a SPI memory.
>>
>> In order to use the Micron memory in its Quad SPI mode, the spi-nor
>> framework needed to be patched to fix the support of Quad/Dual SPI
>> protocols with some memory manufacturers such as Spansion, Micron and
>> Macronix. There are many comments in the source code to explain the
>> implementation choices based on the datasheets from memory manufacturers.
>>
>>
>> This series was based and tested on linux-next-20151207
>>
>> 1 - Atmel QSPI + Micron n25q128a13 (atmel-quadspi.c driver)
>>
>> SPI 1-1-1: This mode was tested replacing SPI_NOR_QUAD by SPI_NOR_FAST as
>>argument to spi_nor_scan() called from atmel_qspi_probe().
>>
>> SPI 1-1-4: Bootloaders (at91bootstrap/uboot) don't enable the Quad SPI
>>mode of the Micron memory. When probed from Linux, the memory
>>uses its Extended SPI mode and replies to the regular Read ID
>>(0x9f) command.
>>
>> SPI 4-4-4: The romcode enabled the Quad SPI mode the of Micron memory
>>before loading the at91bootstrap. When probed from Linux, the
>>memory uses its Quad SPI mode and no longer replies to the
>>regular Read ID (0x9f) command but instead to the Read ID
>>Multiple I/O (0xaf) command. The memory expects ALL commands
>>to use the SPI 4-4-4 protocol.
> 
> I'll admit I'm a little fuzzy on the differences between dual and quad
> modes on various flash manufacturers. Can you help clear it up for me?
> I think some of the comments on patch 2 help too, but I'll just comment
> here for now.
> 
> It looks like the current driver has problems regarding the non 1-x-y
> modes (e.g., 4-4-4), right? But I see that spi-nor.c never tries to
> send a 4_4_4 command; it only sets read_opcode to
> SPINOR_OP_READ_1_1_{1,2,4}. So is this an oversight in patches like
> Bean's patch?
> 
> commit 548cd3ab54da ("mtd: spi-nor: Add quad I/O support for Micron
> SPI NOR")
> 
> Why would we even need to enable quad modes like that, if we're not
> going to send the 4-4-4 opcodes?

First let me clarify one point. This series focuses on Spansion, Macronix
and Micron because when I wrote its patches few months ago, the spi-nor.c
driver supported QSPI protocols only for these three only manufacturers.
Today I notice that now some Winbond memories also use the
SPI_NOR_QUAD_READ flag. Though I try to deal with all manufacturers on a
equal foot, I currently have no knowledge on Windond memories so my
explanations only apply to Spansion, Macronix and Micron memories.

About the SPI 4-4-4 protocol, it is only supported by Micron and Macronix
memories but not by Spansion. Both Micron and Macronix memories provide us
with a special mode, let's call it the Quad SPI mode. As Bean Huo explained
for Micron, once this mode is enabled, the memory expects all commands to
use the SPI 4-4-4 protocol. Hence even if the spi-nor.c driver uses the Fast
Read Quad Output 1-1-4 (0x6b/0x6c) or the Fast Read Quad I/O 1-4-4 (0xeb/0xec)
op codes, the command is interpreted as a Fast Read Quad Command 4-4-4 so must
use the SPI 4-4-4 protocol. As far as I know, there is no currently existing
op code dedicated to the Fast Read Quad Command 4-4-4.

So the op codes may be confusing but when the Quad SPI mode is enabled we
actually use Fast Read 4-4-4 commands.

> 
> My next question (if my understanding is roughly correct) is, do we need
> the 4-4-4 modes, and what risks come with them? I understand we can
> shorten the command and address phases, but does that alone yield much
> performance benefit? And I think the risk is that a given system might
> not be prepared for the flash to be in a 4-4-4 mode, if the boot code
> tries to use 1-x-y commands.
> 

I did not run comparative tests between Fast Read 1-1-4, Fast Read 1-4-4
and Fast Read 4-4-4 yet. Honestly I don't expect much difference. However
performances were not the main purpose when I wrote these patches.
Actually the Quad SPI mode of Macronix and Micron comes with a side effect.
Once enable, not only the memory now expects all commands to use the
SPI 4-4-4 protocol but it no longer replies to the regular Read JEDEC ID
command (0x9f). Instead it replies to a new command, the Read JEDEC ID
Multiple I/O (0xaf).
Now let's imagine that the Quad SPI mode is either permanently enabled at
rese

Re: [PATCH linux-next 0/5] mtd: spi-nor: add driver for Atmel QSPI controller

2015-12-08 Thread Cyrille Pitchen
Le 08/12/2015 11:25, Cyrille Pitchen a écrit :
> Hi Brian,
> 
> Le 07/12/2015 20:34, Brian Norris a écrit :
[...]
>> Also, I see a lot of good comments in patch 2 about Spansion vs.
>> Macronix vs. Micron memories. I wonder if previous developers have
>> completely tested their patches, or if they're just reading the
>> datasheets... so, what kind have testing have you done? Do you have
>> samples of all these flash to test?
>>
> 
> I want to be totally honest on this point: I did NOT test with Macronix
> memories yet simply because I have no such memory from this manufacturer.
> I guess Atmel planed to purchase some samples because we also need to test
> their support in the sama5d2 romcode when booting from QSPI.
> So for the Macronix case, the patches are only based on my current
> understanding of Macronix datasheets (MX66L1G45G, 3V, 1Gb, v1.0.pdf).
> 
> On the other hand I did many tests with both Micron and Spansion memories
> with sama5d2 SoCs, either with Linux or with the sama5d2 romcode ("normal"
> Fast Read x-y-4 but also eXecution In Place using the Continuous Read mode:
> the XIP mode is not relevant for the Linux spi-nor framework but it should
> take care of the "dummy cycles" it sends to avoid entering into the
> Continuous Read mode by mistake).
> I used at least these memories under Linux:
> - Micron n25q128a13: sama5d2 xplained ultra + linux-next 20151207 /
>   at91 linux 4.1
> - Micron n25q256: sama5d2 prototype (FPGA) + at91 linux 3.18
> - Spansion s25fl512: sama5d2 prototype (FPGA) + at91 linux 3.18
> 

I forgot few points. First, I did all Quad SPI tests using the Atmel QSPI
controller and driver.

I did no Dual SPI protocol test yet, only Quad SPI.

I'm able to test neither Quad nor Dual SPI protocols with the Atmel QSPI
protocol + m25p80 driver: this driver is not really suited for handling
the Atmel QSPI controller in its Serial Memory Mode.

However I did some non regression tests with the m25p80 driver used on the
regular Atmel SPI controller and driver (drivers/spi/spi-atmel.c) to
access a at25df312a memory (SPI 1-1-1 protocol).


Nonetheless the m25p80 driver was taken into account when I wrote the series.
Indeed Micron, Macronix and Spansion's datasheets provide tables giving the
number of dummy cycles to use depending on both the SPI bus clock
frequency and the Fast Read command. Hence in spi-nor.c, patch 2 sets
nor->read_dummy to the relevant number of dummy cycles (not bits).

Taking Spansion memories as an example, for their factory default Latency
Code value of 0, they expect:
- 8 dummy cycles for Fast Read 1-1-1 (0x0b / 0x0c)
- 8 dummy cycles for Fast Read 1-1-2 (0x3b / 0x3c)
- 8 dummy cycles for Fast Read 1-1-4 (0x6b / 0x6c)

Fast Read 1-2-2 and 1-4-4 are not used with Spansion memories since the
number of dummy cycles to be used with one of these op codes is not suited
for the m25p80 driver.

For Micron and Macronix, except when their Quad SPI mode is enabled, the
Fast Read 1-1-4 or Fast Read 1-1-2 commands are preferred to the
Fast Read 1-4-4 or Fast Read 1-2-2 commands. The number of dummy cycles is
set to 0 for Read command (0x03) and 8 for other Fast Read commands since
this setting update can be done safely writing into volatile bits inside
configuration registers. A multiple of 8 dummy cycles is suited for the
m25p80_read() implementation.

Then looking at the m25p80 driver, the original (unchanged) cycles/bytes
conversion from the m25p80_read() hook only works with SPI 1-1-x protocols:

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

As a matter of fact, 8 dummy cycles stand for:
-  8 bits (1 byte ) for SPI 1-1-z protocols
- 16 bits (2 bytes) for SPI x-2-z protocols
- 32 bits (4 bytes) for SPI x-4-z protocols

So I should also fix the above conversion in patch 3 to cover more SPI
protocols.


Best Regards,

Cyrille

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


[PATCH linux-next 0/5] mtd: spi-nor: add driver for Atmel QSPI controller

2015-12-07 Thread Cyrille Pitchen
Hi all,

this series of patches adds support to the Atmel QSPI controller available
on sama5d2 SoCs. It was tested on a sama5d2 xplained ultra board with a 
Micron n25q128a13 QSPI memory and a at25df321a SPI memory.

In order to use the Micron memory in its Quad SPI mode, the spi-nor
framework needed to be patched to fix the support of Quad/Dual SPI
protocols with some memory manufacturers such as Spansion, Micron and
Macronix. There are many comments in the source code to explain the
implementation choices based on the datasheets from memory manufacturers.


This series was based and tested on linux-next-20151207

1 - Atmel QSPI + Micron n25q128a13 (atmel-quadspi.c driver)

SPI 1-1-1: This mode was tested replacing SPI_NOR_QUAD by SPI_NOR_FAST as
   argument to spi_nor_scan() called from atmel_qspi_probe().

SPI 1-1-4: Bootloaders (at91bootstrap/uboot) don't enable the Quad SPI
   mode of the Micron memory. When probed from Linux, the memory
   uses its Extended SPI mode and replies to the regular Read ID
   (0x9f) command.

SPI 4-4-4: The romcode enabled the Quad SPI mode the of Micron memory
   before loading the at91bootstrap. When probed from Linux, the
   memory uses its Quad SPI mode and no longer replies to the
   regular Read ID (0x9f) command but instead to the Read ID
   Multiple I/O (0xaf) command. The memory expects ALL commands
   to use the SPI 4-4-4 protocol.

2 - Atmel SPI + at25df321a (m25p80.c driver)

SPI 1-1-1: tested with the m25p80 driver for non regression purpose.


mtd_speedtest was run with the Atmel QSPI controller + Micron memory to
compare the performances of normal and quad SPI protocols. The SPI
bus clock was configured to 83 MHz.

1 - Fast Read 1-1-1

mtd_speedtest: testing eraseblock write speed
mtd_speedtest: eraseblock read speed is 9319 KiB/s
[...]
mtd_speedtest: testing page read speed
mtd_speedtest: page read speed is 6649 KiB/s
[...]
mtd_speedtest: testing 2 page read speed
mtd_speedtest: 2 page read speed is 7757 KiB/s

2 - Fast Read 1-1-4

mtd_speedtest: testing eraseblock read speed
mtd_speedtest: eraseblock read speed is 30117 KiB/s
[...]
mtd_speedtest: testing page read speed
mtd_speedtest: page read speed is 13096 KiB/s
[...]
mtd_speedtest: testing 2 page read speed
mtd_speedtest: 2 page read speed is 18224 KiB/s


So the performance improvements are:
eraseblock read speed (65536 bytes) : +223%
page read speed (512 bytes) :  +97%
2 page read speed (1024 bytes)  : +135%


Best Regards,

Cyrille

Cyrille Pitchen (5):
  mtd: spi-nor: properly detect the memory when it boots in Quad or Dual
mode
  mtd: spi-nor: fix Quad SPI mode support for Spansion, Micron and
Macronix
  mtd: m25p80: add support of dual and quad spi protocols to all
commands
  Documentation: atmel-quadspi: add binding file for Atmel QSPI driver
  mtd: atmel-quadspi: add driver for Atmel QSPI controller

 .../devicetree/bindings/mtd/atmel-quadspi.txt  |  32 +
 drivers/mtd/devices/m25p80.c   | 233 +-
 drivers/mtd/spi-nor/Kconfig|   8 +
 drivers/mtd/spi-nor/Makefile   |   3 +-
 drivers/mtd/spi-nor/atmel-quadspi.c| 877 +
 drivers/mtd/spi-nor/spi-nor.c  | 835 +---
 include/linux/mtd/spi-nor.h|  38 +-
 7 files changed, 1880 insertions(+), 146 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

-- 
1.8.2.2

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


[PATCH linux-next 4/5] Documentation: atmel-quadspi: add binding file for Atmel QSPI driver

2015-12-07 Thread Cyrille Pitchen
This patch documents the DT bindings for the driver of the Atmel QSPI
controller embedded inside sama5d2x SoCs.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 .../devicetree/bindings/mtd/atmel-quadspi.txt  | 32 ++
 1 file changed, 32 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt

diff --git a/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt 
b/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
new file mode 100644
index ..e81f20f9faf1
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
@@ -0,0 +1,32 @@
+* Atmel Quad Serial Peripheral Interface (QSPI)
+
+Required properties:
+- compatible: Should be "atmel,sama5d2-qspi".
+- reg:Should contain the locations and lengths of the base 
registers
+  and the mapped memory.
+- reg-names:  Should contain the resource reg names:
+  - qspi_base: configuration register address space
+  - qspi_mmap: memory mapped address space
+- interrupts: Should contain the interrupt for the device.
+- clocks: The phandle of the clock needed by the QSPI controller.
+- #address-cells: Should be <1>.
+- #size-cells:Should be <0>.
+
+Example:
+
+spi@f002 {
+   compatible = "atmel,sama5d2-qspi";
+   reg = <0xf002 0x100>, <0xd000 0x800>;
+   reg-names = "qpsi_base", "qspi_mmap";
+   interrupts = <52 IRQ_TYPE_LEVEL_HIGH 7>;
+   clocks = <_clk>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   pinctrl-names = "default";
+   pinctrl-0 = <_spi0_default>;
+   status = "okay";
+
+   m25p80@0 {
+   ...
+   };
+};
-- 
1.8.2.2

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


[PATCH linux-next 2/5] mtd: spi-nor: fix Quad SPI mode support for Spansion, Micron and Macronix

2015-12-07 Thread Cyrille Pitchen
This patch reworks the support of Quad and Dual SPI protocols for Micron,
Spansion and Macronix Quad/Dual capable memories. Indeed, in the best
case, only Spansion memories are correctly supported by the current
spi-nor framework.

1 - Micron:
When their Quad SPI mode is enabled, Micron spi-nor memories expect all
commands to use the SPI 4-4-4 protocol. Also when the Dual SPI mode is
enabled, all commands must use the SPI 2-2-2 protocol.

Before this patch, the spi-nor framework used to always enable the Quad
mode when the mode argument of spi_nor_scan() took the value SPI_NOR_QUAD.
That was not suited with drivers only supporting SPI 1-x-4 protocols but
not the 4-4-4 (e.g. the m25p80 driver). Also the SPI controller was not
notified about which SPI protocol to use to transfert command. We cannot
rely only on the op code: in Extended SPI mode the 0x6b command must use
the SPI 1-1-4 protocol whereas in Quad SPi mode the SPI 4-4-4 protocol
must be use instead.

After this patch, the spi-nor framework uses the result of the
spi_nor_read_id() function to choose the right SPI protocol to be used.
If the reg_proto was set to SPI_PROTO_4_4_4, we already know that the Quad
SPI mode is already enabled and that the SPI controller supports the SPI
4-4-4 protocol (otherwise it would have fail to read the JEDEC ID with the
0xaf op code). For the very same reason, if the reg_proto was set to
SPI_PROTO_2_2_2, we already know that the Dual mode is already enabled and
that the SPI controller supports the SPI 2-2-2 protocol.
Otherwise we switch back to the Extended SPI protocol, which supports at
least the Fast Read commands:
- 1-1-1 (0x0b)
- Dual Output 1-1-2 (0x3b)
- Quad Output 1-1-4 (0x6b)

We also safely set the number of dummy cycles to 8 for Fast Read commands
through the Volatile Configuration Register (VCR): some drivers (m25p80)
or SPI controllers only support a number of dummy cycles multiple of 8.
This number may have previouly been set to an unsupported value by an
early bootloader or at reset thanks to the Non-Volatile Configuration
Register.

Finally the XIP bit is always set in the VCR to disable the Continuous
Read mode as we don't want to care about mode cycles.

2 - Macronix:
When the QPI mode is enabled, all commands must use the SPI 4-4-4 protocol
and only the 0xeb op code is supported for Fast Read commands.
Before this patch, the spi-nor framework used to force the QPI mode but
used the 0x6b op code for Fast Read commands when the SPI controller
claims to support Quad SPI mode.
This patch uses the result of spi_nor_read_id() to guess whether the QPI
mode is both enable and supported by the SPI controller (otherwise it
would have failed to read the JEDEC ID with the 0xaf op code).
When the QPI mode is disabled, Macronix memories still support the
following Fast Read commands:
- 1-1-1 (0x0b)
- Dual Output 1-1-2 (0x3b)
- Quad Output 1-1-4 (0x6b)
So if the QPI mode has not already been enabled, there is not need to
enable it. We also avoid the 0xbb (Dual I/O 1-2-2) and 0xeb (Quad I/O
1-4-4) op codes on purpose as we don't want to care about the value to set
in mode cycles not to enter the Continuous Read (Performance Enhance)
mode.

As for Micron memories, the spi-nor framework now safely sets the number
of dummy cycles to 8 thanks to 2 volatile bits inside the Configuration
Register.

3 - Spansion:
As for Macronix, we avoid the 0xbb (Dual I/O 1-2-2) and 0xeb (Quad I/O
1-4-4) op codes on purpose as we don't want to care about the value to set
in mode cycles not to enter in the Continuous Read mode.

Besides, we only care about the Quad Enable bit inside the Configuration
Register (CR) when using Quad operations. In such a case, we first check
its state before trying to set it. Now we also notify the user about the
update of this non-volatile bit.

We also check the Latency Code (LC) in CR to know the exact number of
dummy cycles to use when performing a Fast Read operation. Currently only
the 0x0b, 0x3b and 0x6b op codes are used to perform Fast Read operation
so the number of dummy cycles is always either 0 or 8. Hence no regression
should be introduced.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 783 +-
 include/linux/mtd/spi-nor.h   |  15 +-
 2 files changed, 699 insertions(+), 99 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index bf17736750c1..30b63ab96410 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -138,24 +138,6 @@ static int read_cr(struct spi_nor *nor)
 }
 
 /*
- * Dummy Cycle calculation for different type of read.
- * It can be used to support more commands with
- * different dummy cycle requirements.
- */
-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
-{
-   switch (nor->flash_read) {
-   case SPI_NOR_FAST:
-   case SPI_NOR_DUAL:
-   case SPI_NOR_QUAD:
-  

[PATCH linux-next 3/5] mtd: m25p80: add support of dual and quad spi protocols to all commands

2015-12-07 Thread Cyrille Pitchen
Before this patch, m25p80_read() supported few SPI protocols:
- regular SPI 1-1-1
- SPI Dual Output 1-1-2
- SPI Quad Output 1-1-4
On the other hand, all other m25p80_*() hooks only supported SPI 1-1-1.

However once their Quad mode enabled, Micron and Macronix spi-nor memories
expect all commands to use the SPI 4-4-4 protocol.

Also, once their Dual mode enabled, Micron spi-nor memories expect all
commands to use the SPI-2-2-2 protocol.

So this patch adds support to all currently existing SPI protocols to
cover as many protocols as possible.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/devices/m25p80.c | 233 +++
 1 file changed, 193 insertions(+), 40 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index c9c3b7fa3051..8b09f77eeffb 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -27,22 +27,114 @@
 #include 
 #include 
 
-#defineMAX_CMD_SIZE6
+#defineMAX_CMD_SIZE8
 struct m25p {
struct spi_device   *spi;
struct spi_nor  spi_nor;
u8  command[MAX_CMD_SIZE];
 };
 
+static inline int m25p80_proto2nbits(enum spi_protocol proto,
+unsigned *code_nbits,
+unsigned *addr_nbits,
+unsigned *data_nbits)
+{
+   unsigned code, addr, data;
+
+   switch (proto) {
+   case SPI_PROTO_1_1_1:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_SINGLE;
+   data = SPI_NBITS_SINGLE;
+   break;
+
+   case SPI_PROTO_1_1_2:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_SINGLE;
+   data = SPI_NBITS_DUAL;
+   break;
+
+   case SPI_PROTO_1_1_4:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_SINGLE;
+   data = SPI_NBITS_QUAD;
+   break;
+
+   case SPI_PROTO_1_2_2:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_DUAL;
+   data = SPI_NBITS_DUAL;
+   break;
+
+   case SPI_PROTO_1_4_4:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_QUAD;
+   data = SPI_NBITS_QUAD;
+   break;
+
+   case SPI_PROTO_2_2_2:
+   code = SPI_NBITS_DUAL;
+   addr = SPI_NBITS_DUAL;
+   data = SPI_NBITS_DUAL;
+   break;
+
+   case SPI_PROTO_4_4_4:
+   code = SPI_NBITS_QUAD;
+   addr = SPI_NBITS_QUAD;
+   data = SPI_NBITS_QUAD;
+   break;
+
+   default:
+   return -EINVAL;
+
+   }
+
+   if (code_nbits)
+   *code_nbits = code;
+   if (addr_nbits)
+   *addr_nbits = addr;
+   if (data_nbits)
+   *data_nbits = data;
+
+   return 0;
+}
+
 static int m25p80_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len)
 {
struct m25p *flash = nor->priv;
struct spi_device *spi = flash->spi;
+   unsigned code_nbits, data_nbits;
+   struct spi_transfer xfers[2];
int ret;
 
-   ret = spi_write_then_read(spi, , 1, val, len);
+   /* Check the total length of command op code and data. */
+   if (len + 1 > MAX_CMD_SIZE)
+   return -EINVAL;
+
+   /* Get transfer protocols (addr_nbits is not relevant here). */
+   ret = m25p80_proto2nbits(nor->reg_proto,
+_nbits, NULL, _nbits);
+   if (ret < 0)
+   return ret;
+
+   /* Set up transfers. */
+   memset(xfers, 0, sizeof(xfers));
+
+   flash->command[0] = code;
+   xfers[0].len = 1;
+   xfers[0].tx_buf = flash->command;
+   xfers[0].tx_nbits = code_nbits;
+
+   xfers[1].len = len;
+   xfers[1].rx_buf = >command[1];
+   xfers[1].rx_nbits = data_nbits;
+
+   /* Process command. */
+   ret = spi_sync_transfer(spi, xfers, 2);
if (ret < 0)
dev_err(>dev, "error %d reading %x\n", ret, code);
+   else
+   memcpy(val, >command[1], len);
 
return ret;
 }
@@ -65,12 +157,42 @@ static int m25p80_write_reg(struct spi_nor *nor, u8 
opcode, u8 *buf, int len)
 {
struct m25p *flash = nor->priv;
struct spi_device *spi = flash->spi;
+   unsigned code_nbits, data_nbits, num_xfers = 1;
+   struct spi_transfer xfers[2];
+   int ret;
+
+   /* Check the total length of command op code and data. */
+   if (buf && (len + 1 > MAX_CMD_SIZE))
+   return -EINVAL;
+
+   /* Get transfer protocols (addr_nbits is not relevant here). */
+   ret = m25p80_proto2nbits(nor->reg_proto,
+_nbits, NULL, _nbits);
+   if (ret < 0)
+   

[PATCH linux-next 1/5] mtd: spi-nor: properly detect the memory when it boots in Quad or Dual mode

2015-12-07 Thread Cyrille Pitchen
The quad (or dual) mode of a spi-nor memory may be enabled at boot time by
non-volatile bits in some setting register. Also such a mode may have
already been enabled at early stage by some boot loader.

Hence, we should not guess the spi-nor memory is always configured for the
regular SPI 1-1-1 protocol.

Micron and Macronix memories, once their Quad (or dual for Micron) mode
enabled, no longer process the regular JEDEC Read ID (0x9f) command but
instead reply to a new command: JEDEC Read ID Multiple I/O (0xaf).
Besides, in Quad mode both memory manufacturers expect ALL commands to
use the SPI 4-4-4 protocol. For Micron memories, enabling their Dual mode
implies to use the SPI 2-2-2 protocol for ALL commands.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 52 +++
 include/linux/mtd/spi-nor.h   | 23 +--
 2 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 3b2460efc019..bf17736750c1 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -73,6 +73,11 @@ struct flash_info {
 
 #define JEDEC_MFR(info)((info)->id[0])
 
+struct read_id_config {
+   enum read_mode  mode;
+   enum spi_protocol   proto;
+};
+
 static const struct flash_info *spi_nor_match_id(const char *name);
 
 /*
@@ -867,11 +872,16 @@ static const struct flash_info spi_nor_ids[] = {
{ },
 };
 
-static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
+static const struct flash_info *spi_nor_read_id(struct spi_nor *nor,
+   enum read_mode mode)
 {
-   int tmp;
+   int i, tmp;
u8  id[SPI_NOR_MAX_ID_LEN];
const struct flash_info *info;
+   static const struct read_id_config configs[] = {
+   {SPI_NOR_QUAD, SPI_PROTO_4_4_4},
+   {SPI_NOR_DUAL, SPI_PROTO_2_2_2}
+   };
 
tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
if (tmp < 0) {
@@ -879,6 +889,34 @@ static const struct flash_info *spi_nor_read_id(struct 
spi_nor *nor)
return ERR_PTR(tmp);
}
 
+   /* Special case for Micron/Macronix qspi nor. */
+   if ((id[0] == 0xff && id[1] == 0xff && id[2] == 0xff) ||
+   (id[0] == 0x00 && id[1] == 0x00 && id[2] == 0x00))
+   for (i = 0; i < ARRAY_SIZE(configs); ++i) {
+   if (configs[i].mode != mode)
+   continue;
+
+   /* Set this protocol for all commands. */
+   nor->reg_proto = configs[i].proto;
+   nor->read_proto = configs[i].proto;
+   nor->write_proto = configs[i].proto;
+   nor->erase_proto = configs[i].proto;
+
+   /*
+* Multiple I/O Read ID only returns the Manufacturer ID
+* (1 byte) and the Device ID (2 bytes). So we reset the
+* remaining bytes.
+*/
+   memset(id, 0, sizeof(id));
+   tmp = nor->read_reg(nor, SPINOR_OP_MIO_RDID, id, 3);
+   if (tmp < 0) {
+   dev_dbg(nor->dev,
+   "error %d reading JEDEC ID Multi I/O\n",
+   tmp);
+   return ERR_PTR(tmp);
+   }
+   }
+
for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) {
info = _nor_ids[tmp];
if (info->id_len) {
@@ -1178,11 +1216,17 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
if (ret)
return ret;
 
+   /* Reset SPI protocol for all commands */
+   nor->erase_proto = SPI_PROTO_1_1_1;
+   nor->read_proto = SPI_PROTO_1_1_1;
+   nor->write_proto = SPI_PROTO_1_1_1;
+   nor->reg_proto = SPI_PROTO_1_1_1;
+
if (name)
info = spi_nor_match_id(name);
/* Try to auto-detect if chip name wasn't specified or not found */
if (!info)
-   info = spi_nor_read_id(nor);
+   info = spi_nor_read_id(nor, mode);
if (IS_ERR_OR_NULL(info))
return -ENOENT;
 
@@ -1193,7 +1237,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
if (name && info->id_len) {
const struct flash_info *jinfo;
 
-   jinfo = spi_nor_read_id(nor);
+   jinfo = spi_nor_read_id(nor, mode);
if (IS_ERR(jinfo)) {
return PTR_ERR(jinfo);
  

[PATCH linux-next 5/5] mtd: atmel-quadspi: add driver for Atmel QSPI controller

2015-12-07 Thread Cyrille Pitchen
This driver add support to the new Atmel QSPI controller embedded into
sama5d2x SoCs. It expects a NOR memory to be connected to the QSPI
controller.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi-nor/Kconfig |   8 +
 drivers/mtd/spi-nor/Makefile|   3 +-
 drivers/mtd/spi-nor/atmel-quadspi.c | 877 
 3 files changed, 887 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 0dc927540b3d..15f45dbbfe0d 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -37,6 +37,14 @@ config SPI_FSL_QUADSPI
  This controller does not support generic SPI. It only supports
  SPI NOR.
 
+config SPI_ATMEL_QUADSPI
+   tristate "Atmel Quad SPI Controller"
+   depends on OF && HAS_DMA && (ARCH_AT91 || COMPILE_TEST)
+   help
+ This enables support for the Quad SPI controller in master mode.
+ This driver does not support generic SPI. The implementation only
+ supports SPI NOR.
+
 config SPI_NXP_SPIFI
tristate "NXP SPI Flash Interface (SPIFI)"
depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 0bf3a7f81675..0cbed0e4ae8c 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_MTD_SPI_NOR)  += spi-nor.o
 obj-$(CONFIG_SPI_FSL_QUADSPI)  += fsl-quadspi.o
-obj-$(CONFIG_MTD_MT81xx_NOR)+= mtk-quadspi.o
+obj-$(CONFIG_MTD_MT81xx_NOR)   += mtk-quadspi.o
+obj-$(CONFIG_SPI_ATMEL_QUADSPI)+= atmel-quadspi.o
 obj-$(CONFIG_SPI_NXP_SPIFI)+= nxp-spifi.o
diff --git a/drivers/mtd/spi-nor/atmel-quadspi.c 
b/drivers/mtd/spi-nor/atmel-quadspi.c
new file mode 100644
index ..bdebfdc92842
--- /dev/null
+++ b/drivers/mtd/spi-nor/atmel-quadspi.c
@@ -0,0 +1,877 @@
+/*
+ * Driver for Atmel QSPI Controller
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen <cyrille.pitc...@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This driver is based on drivers/mtd/spi-nor/fsl-quadspi.c from Freescale.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+/* QSPI register offsets */
+#define QSPI_CR  0x  /* Control Register */
+#define QSPI_MR  0x0004  /* Mode Register */
+#define QSPI_RD  0x0008  /* Receive Data Register */
+#define QSPI_TD  0x000c  /* Transmit Data Register */
+#define QSPI_SR  0x0010  /* Status Register */
+#define QSPI_IER 0x0014  /* Interrupt Enable Register */
+#define QSPI_IDR 0x0018  /* Interrupt Disable Register */
+#define QSPI_IMR 0x001c  /* Interrupt Mask Register */
+#define QSPI_SCR 0x0020  /* Serial Clock Register */
+
+#define QSPI_IAR 0x0030  /* Instruction Address Register */
+#define QSPI_ICR 0x0034  /* Instruction Code Register */
+#define QSPI_IFR 0x0038  /* Instruction Frame Register */
+
+#define QSPI_SMR 0x0040  /* Scrambling Mode Register */
+#define QSPI_SKR 0x0044  /* Scrambling Key Register */
+
+#define QSPI_WPMR0x00E4  /* Write Protection Mode Register */
+#define QSPI_WPSR0x00E8  /* Write Protection Status Register */
+
+#define QSPI_VERSION 0x00FC  /* Version Register */
+
+
+/* Bitfields in QSPI_CR (Control Register) */
+#define QSPI_CR_QSPIEN  BIT(0)
+#define QSPI_CR_QSPIDIS BIT(1)
+#define QSPI_CR_SWRST   BIT(7)
+#define QSPI_CR_LASTXFERBIT(24)
+
+/* Bitfields in QSPI_MR (Mode Register) */
+#define QSPI_MR_SSM BIT(0)
+#define QSPI_MR_LLB BIT(1)
+#define QSPI_MR_WDRBT   BIT(2)
+#define QSPI_MR_SMRMBIT(3)
+#define QSPI_MR_CSMODE_MASK GENMASK(5, 4)
+#define QSPI_MR_CSMODE_NOT_RELOADED (0 << 4)
+#define QSPI_MR_CSMODE_LASTXFER (1 << 4)
+#define QSPI_MR_CSMODE_SYSTEMATICALLY   (2 << 4)
+#define QSPI_MR_NBBITS_MASK GENMASK(11, 8)
+#define QSPI_MR_NBBITS(n)   n) - 8) << 8) & 
QSPI_MR_NBBITS_MASK)
+#define QSP

Re: [PATCH v4 3/5] mtd: devices: m25p80: add support for mmap read request

2015-12-03 Thread Cyrille Pitchen
Hi Vignesh,

Le 30/11/2015 06:15, Vignesh R a écrit :
> Certain spi controllers may provide accelerated interface to read from
> m25p80 type flash devices. This interface provides better read
> performance than regular SPI interface.
> Call spi_flash_read(), if supported, to make use of such interface.
> 
> Signed-off-by: Vignesh R 
> ---
> 
> v4: 
>  * Use spi_flash_read_message struct to pass args.
>  * support passing of opcode/addr/data nbits.
> 
>  drivers/mtd/devices/m25p80.c | 20 
>  1 file changed, 20 insertions(+)
> 
> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> index fe9ceb7b5405..00094a668c62 100644
> --- a/drivers/mtd/devices/m25p80.c
> +++ b/drivers/mtd/devices/m25p80.c
> @@ -131,6 +131,26 @@ static int m25p80_read(struct spi_nor *nor, loff_t from, 
> size_t len,
>   /* convert the dummy cycles to the number of bytes */
>   dummy /= 8;
>  
> + if (spi_flash_read_supported(spi)) {
> + struct spi_flash_read_message msg;
> + int ret;
> +
> + msg.buf = buf;
> + msg.from = from;
> + msg.len = len;
> + msg.read_opcode = nor->read_opcode;
> + msg.addr_width = nor->addr_width;
> + msg.dummy_bytes = dummy;
> + /* TODO: Support other combinations */
> + msg.opcode_nbits = SPI_NBITS_SINGLE;
> + msg.addr_nbits = SPI_NBITS_SINGLE;
> + msg.data_nbits = m25p80_rx_nbits(nor);

I wanted to let you know that the support of other SPI protocols has already
been implemented by this series:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-September/371170.html

patches 2 & 3 handle the probing of the (Q)SPI memory in spi_nor_scan() and
select the right protocols for register read/write, memory read, memory write,
and memory erase operations. The choice is done according to both the memory
and SPI controller capabilities.

patch 4 updates the m25p80 driver to take advantage of the bandwidth increase
allowed by QSPI protocols. For instance, the Atmel QSPI controller, like TI
one, maps the SPI NOR memory to the system bus. Yesterday I ran mtd_speedtest
to compare Fast Read 1-1-1 (0x0b) and Fast Read 1-1-4 (0x6b). The SPI clock
frequency was limited to 83MHz. The QSPI memory is a Micron n25q128a13.

I only had to change the mode argument of spi_nor_scan() from SPI_NOR_QUAD to
SPI_NOR_FAST in the atmel_quadspi driver (based on fsl-quadspi driver from
Freescale since Atmel's driver also uses the system bus mapping for memory
write operations) to force the spi-nor framework to choose the SPI 1-1-1
protocol instead of the SPI-1-1-4.

1 - Fast Read 1-1-1

mtd_speedtest: testing eraseblock write speed
mtd_speedtest: eraseblock read speed is 9319 KiB/s
[...]
mtd_speedtest: testing page read speed
mtd_speedtest: page read speed is 6649 KiB/s
[...]
mtd_speedtest: testing 2 page read speed
mtd_speedtest: 2 page read speed is 7757 KiB/s

2 - Fast Read 1-1-4

mtd_speedtest: testing eraseblock read speed
mtd_speedtest: eraseblock read speed is 30117 KiB/s
[...]
mtd_speedtest: testing page read speed
mtd_speedtest: page read speed is 13096 KiB/s
[...]
mtd_speedtest: testing 2 page read speed
mtd_speedtest: 2 page read speed is 18224 KiB/s

So the performance improvements are:
eraseblock read speed (65536 bytes) : +223%
page read speed (512 bytes) :  +97%
2 page read speed (1024 bytes)  : +135%


That's why I believe that you could take advantage of these performance
improvements in the TI (Q)SPI controller driver.


Also please note that you may have to add in the struct spi_flash_read_message
two other fields for the number of option/mode cycles and their value.
Option/mode cycles are sent between the address and dummy cycles. They are
used by some memory manufacturers such as Spansion, Micron and Macronix to
enter/leave their continuous read mode.
So if uninitialized dummy cycles are interpreted by the QSPI memory as
option/mode cycles, depending on the actual value, the memory may enter by
mistake in continuous mode. Once in continuous mode, the command op code byte
must not be sent and is not expected by the memory: the memory implicitly uses
the read op code sent in the SPI message which triggered the memory to enter
continuous read mode. Next SPI messages start from the address cycles until
the right option/mode cycles are sent to leave the continuous read mode.

Currently the mtd layer doesn't use this feature but it should be aware of it.
That's why I believe we'll have to address this point in spi_nor_scan() and the
"regular" m25p80() sooner or later.

> +
> + ret = spi_flash_read(spi, );
> + *retlen = msg.retlen;
> + return ret;
> + }
> +
>   spi_message_init();
>   memset(t, 0, (sizeof t));
>  
> 

Best regards,

Cyrille
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to 

Re: [PATCH v3 1/5] spi: introduce mmap read support for spi flash devices

2015-11-13 Thread Cyrille Pitchen
Hi Brian,

Le 11/11/2015 08:20, Brian Norris a écrit :
> Hi,
> 
> On Wed, Nov 11, 2015 at 12:20:46PM +0530, R, Vignesh wrote:
>> On 11/11/2015 4:53 AM, Brian Norris wrote:
>>> On Tue, Nov 10, 2015 at 10:59:55AM +0530, Vignesh R wrote:
 diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
 index cce80e6dc7d1..2f2c431b8917 100644Hi
 --- a/include/linux/spi/spi.h
 +++ b/include/linux/spi/spi.h
 @@ -361,6 +361,11 @@ static inline void spi_unregister_driver(struct 
 spi_driver *sdrv)
   * @handle_err: the subsystem calls the driver to handle an error that 
 occurs
   *in the generic implementation of transfer_one_message().
   * @unprepare_message: undo any work done by prepare_message().
 + * @spi_mtd_mmap_read: some spi-controller hardwares provide memory.
 + * Flash drivers (like m25p80) can request memory
 + * mapped read via this method. This interface
 + * should only be used by mtd flashes and cannot be
 + * used by other spi devices.
   * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
   *number. Any individual value may be -ENOENT for CS lines that
   *are not GPIOs (driven by the SPI controller itself).
 @@ -507,6 +512,11 @@ struct spi_master {
   struct spi_message *message);
int (*unprepare_message)(struct spi_master *master,
 struct spi_message *message);
 +  int (*spi_mtd_mmap_read)(struct  spi_device *spi,
 +   loff_t from, size_t len,
 +   size_t *retlen, u_char *buf,
 +   u8 read_opcode, u8 addr_width,
 +   u8 dummy_bytes);
>>>
>>> Is this API really sufficient? There are actually quite a few other
>>> flash-related parameters that might be relevant to a controller. I
>>> presume you happen not hit them because of the particular cases you're
>>> using this for right now, but:
>>>
>>>  * How many I/O lines are being used? These can vary depending on the
>>>type of flash and the number of I/O lines supported by the controller
>>>and connected on the board.
>>>
>>
>> This API communicates whatever data is currently communicated via
>> spi_message through spi_sync/transfer_one interfaces.
> 
> No it doesn't. A spi_message consists of a list of spi_transfer's, and
> each spi_transfer has tx_nbits and rx_nbits fields.
> 
>>>  * The previous point can vary across parts of the message. There are
>>>various combinations of 1/2/4 lines used for opcode/address/data. We
>>>only support a few of those combinations in m25p80 right now, but
>>>you're not specifying any of that in this API. I guess you're just
>>>making assumptions? (BTW, I think there are others having problems
>>>with the difference between different "quad" modes on Micron flash; I
>>>haven't sorted through all the discussion there.)
>>>
>>
>> How is the spi controller currently being made aware of this via
>> m25p80_read / spi_sync() interface? AFAIK, mode field of spi_device
>> struct tell whether to do normal/dual/quad read but there is no info
>> communicated wrt 1/2/4 opcode/address/data combinations.
> 
> Yes there is. m25p80 fills out spi_transfer::rx_nbits. Currently, we
> only use this for the data portion, but it's possible to support more
> lines for the address and opcode portions too, using the rx_nbits for
> the opcode and address spi_transfer struct(s) (currently, m25p80_read()
> uses 2 spi_transfers per message, where the first one contains opcode +
> address + dummy on a single line, and the second transfer receives the
> data on 1, 2, or 4 lines).
> 

In September I've sent a series of patches to enhance the support of QSPI flash
memories. Patch 4 was dedicated to the m25p80 driver and set the
rx_nbits / tx_nbits fields of spi_transfer struct(s) in order to configure the
number of I/O lines independently for the opcode, address and data parts.
The work was done for m25p80_read() but also for _read_reg(), _write_reg() and
_write().
The patched m25p80 driver was then tested with an at25 memory to check non-
regression.

This series of patches also added 4 enum spi_protocol fields inside struct
spi_nor so the spi-nor framework can tell the (Q)SPI controller driver what SPI
protocol should be use for erase, read, write and register read/write
operations, depending on the memory manufacturer and the command opcode.
This was done to better support Micron, Spansion and Macronix QSPI memories.

I have tested the series with Micron QSPI memories and Atmel QSPI controller
and I guess Marek also tested it on his side with Spansion QSPI memories and
another QSPI controller.

So if it can help other developers to develop QSPI controller drivers, the
series is still available there:

for the whole series:

Re: [PATCH linux-next 0/4] mtd: spi-nor: fix Quad SPI memory support

2015-11-02 Thread Cyrille Pitchen
Le 02/11/2015 02:07, Marek Vasut a écrit :
> On Friday, September 18, 2015 at 05:49:24 PM, Cyrille Pitchen wrote:
>> Hi all,
> 
> Hi!
> 
Hi Marek!

>> this series of patches fixes the QSPI support mostly for Micron and
>> Macronix memories. There are also some updates for Spansion memories.
>> There are also many comments to explain the implementation choices based
>> on the datasheets from memory manufacturers.
>>
>> The series was backported to a at91-4.1 kernel then tested on a sama5d2
>> xplained board, which embeds a at25df321a memory on a SPI controller and
>> a Micron n25q128a13 QSPI memory on the new Atmel QSPI controller.
>>
>> The at25 memory was used to check non regression on the m25p80 driver
>> whereas the Micron memory was used to test the fixes of the spi-nor
>> framework. The driver for the Atmel QSPI controller will be sent in a
>> dedicated series.
> 
> Are there any news on this patch series? I'd like to use that for my own
> QSPI driver (the Cadence one), so I'd like to check on the status. Are you
> still working on this please ?
> 
Nothing new from my side. This series of patches should have taken into account
all the comments I'd received from previous series. At least, I hope so.
If I forgot some points or if something is still missing, let me know and I'll
update the series accordingly.

I also wait for a kind of agreement on how we could update the framework API
so that more QSPI memories could be supported. I have already written a driver
for an Atmel QSPI controller. This driver is based on this series of patches.
I have to know what the updated API will be before sending another series for
the QSPI controller driver. So this series is one proposal for some API updates
but other proposals may exist.

I've asked Brian on IRC for review and pieces of advice on how he thinks the
work should be done. I've understood he's right now a little bit busy. I'm fine
with it. I also often have to deal with many topics almost in the same time so
I can understand whether he needs more time.

Anyway, I guess Brian has already started to review these patches since last
Friday he referred to a previous talk we had about some leading space:

http://lists.infradead.org/pipermail/linux-mtd/2015-October/062956.html


> Thanks!
> 
> Best regards,
> Marek Vasut
> 

Best regards,

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


Re: [PATCH 1/2] i2c: at91: add DT property for the HOLD field of TWIHS_CWGR

2015-09-30 Thread Cyrille Pitchen
Hi all,

it looks good to me.

Le 30/09/2015 10:47, Ludovic Desroches a écrit :
> From: Wenyou Yang <wenyou.y...@atmel.com>
> 
> Add the HOLD field setting in order to support I2C slave devices which need
> a longer hold time of the data.
> Since it depends on the slave devices connected to the bus, add a DT
> property "atmel,twd-hold-cycles" to specify this HOLD field.
> 
> Signed-off-by: Wenyou Yang <wenyou.y...@atmel.com>
> Signed-off-by: Ludovic Desroches <ludovic.desroc...@atmel.com>

Acked-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>

> ---
>  drivers/i2c/busses/i2c-at91.c | 16 +---
>  1 file changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
> index 1c758cd..06e66ef 100644
> --- a/drivers/i2c/busses/i2c-at91.c
> +++ b/drivers/i2c/busses/i2c-at91.c
> @@ -64,6 +64,7 @@
>  #define  AT91_TWI_IADR   0x000c  /* Internal Address Register */
>  
>  #define  AT91_TWI_CWGR   0x0010  /* Clock Waveform Generator Reg 
> */
> +#define  AT91_TWI_CWGR_HOLD(x)   (((x) & 0x1f) << 24)
>  
>  #define  AT91_TWI_SR 0x0020  /* Status Register */
>  #define  AT91_TWI_TXCOMP BIT(0)  /* Transmission Complete */
> @@ -185,7 +186,8 @@ static void at91_init_twi_bus(struct at91_twi_dev *dev)
>   * Calculate symmetric clock as stated in datasheet:
>   * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset))
>   */
> -static void at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
> +static void at91_calc_twi_clock(struct at91_twi_dev *dev,
> + int twi_clk, u32 twd_hold)
>  {
>   int ckdiv, cdiv, div;
>   struct at91_twi_pdata *pdata = dev->pdata;
> @@ -204,7 +206,9 @@ static void at91_calc_twi_clock(struct at91_twi_dev *dev, 
> int twi_clk)
>   cdiv = 255;
>   }
>  
> - dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv;
> + dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv
> + | AT91_TWI_CWGR_HOLD(twd_hold);
> +
>   dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv);
>  }
>  
> @@ -936,6 +940,7 @@ static int at91_twi_probe(struct platform_device *pdev)
>   int rc;
>   u32 phy_addr;
>   u32 bus_clk_rate;
> + u32 twd_hold_cycles;
>  
>   dev = devm_kzalloc(>dev, sizeof(*dev), GFP_KERNEL);
>   if (!dev)
> @@ -992,7 +997,12 @@ static int at91_twi_probe(struct platform_device *pdev)
>   if (rc)
>   bus_clk_rate = DEFAULT_TWI_CLK_HZ;
>  
> - at91_calc_twi_clock(dev, bus_clk_rate);
> + rc = of_property_read_u32(dev->dev->of_node,
> +   "atmel,twd-hold-cycles", _hold_cycles);
> + if (rc)
> + twd_hold_cycles = 0;
> +
> + at91_calc_twi_clock(dev, bus_clk_rate, twd_hold_cycles);
>   at91_init_twi_bus(dev);
>  
>   snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91");
> 

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


[PATCH v2 1/2] ASoC: atmel-i2s: add DT bindings for I2S controller

2015-09-29 Thread Cyrille Pitchen
This patch adds DT bindings for the new Atmel I2S controller embedded
inside sama5d2x SoCs.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 .../devicetree/bindings/sound/atmel-i2s.txt| 43 ++
 1 file changed, 43 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/atmel-i2s.txt

diff --git a/Documentation/devicetree/bindings/sound/atmel-i2s.txt 
b/Documentation/devicetree/bindings/sound/atmel-i2s.txt
new file mode 100644
index ..83bc6b9070bf
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/atmel-i2s.txt
@@ -0,0 +1,43 @@
+* Atmel I2S controller
+
+Required properties:
+- compatible: Should be "atmel,sama5d2-i2s".
+- reg:Should be the physical base address of the controller and the
+  length of memory mapped region.
+- interrupts: Should contain the interrupt for the controller.
+- dmas:   Should be a list of pairs of DMA controller phandle and 
flags.
+- dma-names:  Should be a list of DMA channel name among "rx", "tx" or
+  "rx-tx".
+- clocks: Should be a list of phandles of clocks used by the controller
+  (1).
+- clock-names:Should be a list matching the clocks phandles list:
+  - "pclk" (peripheral clock) Required.
+  - "gclk" (generated clock) Optional (1).
+  - "aclk" (Audio PLL clock) Optional (1).
+
+Optional properties:
+- pinctrl-0:  Should specify pin control groups used for this controller.
+- princtrl-names: Should contain only one value - "default".
+
+
+(1) : Only the peripheral clock is required. The generated clock and the Audio
+  PLL clock are optional and should only be set together.
+
+Example:
+
+   i2s@f805 {
+   compatible = "atmel,sama5d2-i2s";
+   reg = <0xf805 0x300>;
+   interrupts = <54 IRQ_TYPE_LEVEL_HIGH 7>;
+   dmas = <
+   (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+AT91_XDMAC_DT_PERID(31))>,
+  <
+   (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+AT91_XDMAC_DT_PERID(32))>;
+   dma-names = "tx", "rx";
+   clocks = <_clk>, <_gclk>, <_pll_pmc>;
+   clock-names = "pclk", "gclk", "aclk";
+   pinctrl-names = "default";
+   pinctrl-0 = <_i2s0_default>;
+   };
-- 
1.8.2.2

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


[PATCH v2 2/2] ASoC: atmel-i2s: add driver for the new Atmel I2S controller

2015-09-29 Thread Cyrille Pitchen
This patch adds support for the Atmel I2S controller embedded into
sama5d2x SoCs.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 sound/soc/atmel/Kconfig |  10 +
 sound/soc/atmel/Makefile|   2 +
 sound/soc/atmel/atmel-i2s.c | 760 
 3 files changed, 772 insertions(+)
 create mode 100644 sound/soc/atmel/atmel-i2s.c

diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 1489cd461aec..c026c207a386 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -30,6 +30,16 @@ config SND_ATMEL_SOC_SSC
default y if SND_ATMEL_SOC_SSC_DMA=y || SND_ATMEL_SOC_SSC_PDC=y
default m if SND_ATMEL_SOC_SSC_DMA=m || SND_ATMEL_SOC_SSC_PDC=m
 
+config SND_ATMEL_SOC_I2S
+   tristate "SoC Audio support for the Atmel I2S module"
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   select REGMAP_MMIO
+   depends on OF && (ARCH_AT91 || COMPILE_TEST)
+   help
+ Say Y or M if you want to add support for codecs attached to
+ the Atmel I2S interface. You will also need
+ to select the audio interfaces to support below.
+
 config SND_AT91_SOC_SAM9G20_WM8731
tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation 
board"
depends on ARCH_AT91 || COMPILE_TEST
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index b327e5cc8de3..4d960464aecb 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -2,10 +2,12 @@
 snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o
 snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
 snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
+snd-soc-atmel-i2s-objs := atmel-i2s.o
 
 obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o
 obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o
 obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
+obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o
 
 # AT91 Machine Support
 snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c
new file mode 100644
index ..9e15acabbaab
--- /dev/null
+++ b/sound/soc/atmel/atmel-i2s.c
@@ -0,0 +1,760 @@
+/*
+ * Driver for Atmel I2S controller
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen <cyrille.pitc...@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ATMEL_I2SC_MAX_TDM_CHANNELS8
+
+/*
+ *  I2S Controller Register map 
+ */
+#define ATMEL_I2SC_CR  0x  /* Control Register */
+#define ATMEL_I2SC_MR  0x0004  /* Mode Register */
+#define ATMEL_I2SC_SR  0x0008  /* Status Register */
+#define ATMEL_I2SC_SCR 0x000c  /* Status Clear Register */
+#define ATMEL_I2SC_SSR 0x0010  /* Status Set Register */
+#define ATMEL_I2SC_IER 0x0014  /* Interrupt Enable Register */
+#define ATMEL_I2SC_IDR 0x0018  /* Interrupt Disable Register */
+#define ATMEL_I2SC_IMR 0x001c  /* Interrupt Mask Register */
+#define ATMEL_I2SC_RHR 0x0020  /* Receiver Holding Register */
+#define ATMEL_I2SC_THR 0x0024  /* Transmitter Holding Register */
+#define ATMEL_I2SC_VERSION 0x0028  /* Version Register */
+
+
+/*
+ *  Control Register (Write-only) 
+ */
+#define ATMEL_I2SC_CR_RXEN BIT(0)  /* Receiver Enable */
+#define ATMEL_I2SC_CR_RXDISBIT(1)  /* Receiver Disable */
+#define ATMEL_I2SC_CR_CKEN BIT(2)  /* Clock Enable */
+#define ATMEL_I2SC_CR_CKDISBIT(3)  /* Clock Disable */
+#define ATMEL_I2SC_CR_TXEN BIT(4)  /* Transmitter Enable */
+#define ATMEL_I2SC_CR_TXDISBIT(5)  /* Transmitter Disable */
+#define ATMEL_I2SC_CR_SWRSTBIT(7)  /* Software Reset */
+
+
+/*
+ *  Mode Register (Read/Write) 
+ */
+#define ATMEL_I2SC_MR_MODE_MASKGENMASK(0, 0)
+#define ATMEL_I2SC_MR_MODE_SLAVE   (0 << 0)
+#define ATMEL_I2SC_MR_MODE_MASTER  (1 << 0)
+
+#define ATMEL_I2SC_MR_DATALENGTH_MASK  GENMASK(4, 2)
+#define ATMEL_I2SC_MR_DATALENGTH_32_BITS   (0 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_24_BITS   (1 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_20_BITS   (2 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_18_BITS 

Re: [PATCH 2/2] ASoC: atmel-i2s: add driver for the new Atmel I2S controller

2015-09-29 Thread Cyrille Pitchen
Le 28/09/2015 17:05, Cyrille Pitchen a écrit :
[...]
> + /* Get audio clocks to generate the I2S Master Clock (I2S_MCK) */
> + dev->aclk = devm_clk_get(>dev, "aclk");
> + dev->gclk = devm_clk_get(>dev, "gclk");
> + if (IS_ERR(dev->aclk) && IS_ERR(dev->gclk)) {
> + /* Master Mode not supported */
> + dev->aclk = NULL;
> + dev->gclk = NULL;
> + } else if (IS_ERR(dev->gclk)) {
> + err = PTR_ERR(dev->gclk);
> + dev_err(>dev,
> + "failed to get the PMC generated clock: %d\n", err);
> + return err;
> + } else if (IS_ERR(dev->aclk)) {
> + err = PTR_ERR(dev->aclk);
> + dev_err(>dev,
> + "failed to get the PLL audio clock: %d\n", err);
> + return err;
> + }
> +
> + /* Do hardware specific settings to initialize I2S_MCK generator */
> + if (dev->caps && dev->caps->mck_init) {
> + err = dev->caps->mck_init(dev, np);
> + if (err)
> + return err;
> + }
> +
> + /* Enable the peripheral clock. */
> + err = clk_prepare_enable(dev->pclk);
> + if (err)
> + return err;
> +
> + dev->dev = >dev;
> + dev->regmap = regmap;
> + platform_set_drvdata(pdev, dev);

those last 3 lines should be moved before calling dev->caps->mck_init(),
otherwise dev->dev would not be initialized yet if dev_err() is called by
atmel_i2s_sama5d2_mck_init().

Will be fixed in the next series.
[...]
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 0/2] ASoC: add driver for Atmel I2S controller

2015-09-29 Thread Cyrille Pitchen
This series of patches adds support to the new Atmel I2S controller embedded
on sama5d2 SoCs.


ChangeLog

v2:
- initialize dev->dev before calling dev->caps->mck_init().

Cyrille Pitchen (2):
  ASoC: atmel-i2s: add DT bindings for I2S controller
  ASoC: atmel-i2s: add driver for the new Atmel I2S controller

 .../devicetree/bindings/sound/atmel-i2s.txt|  43 ++
 sound/soc/atmel/Kconfig|  10 +
 sound/soc/atmel/Makefile   |   2 +
 sound/soc/atmel/atmel-i2s.c| 760 +
 4 files changed, 815 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/atmel-i2s.txt
 create mode 100644 sound/soc/atmel/atmel-i2s.c

-- 
1.8.2.2

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


[PATCH 0/2] ASoc: add driver for Atmel I2S controller

2015-09-28 Thread Cyrille Pitchen
This series of patches add support to the new Atmel I2S controller embedded
on sama5d2 SoCs.

Cyrille Pitchen (2):
  ASoC: atmel-i2s: add DT bindings for I2S controller
  ASoC: atmel-i2s: add driver for the new Atmel I2S controller

 .../devicetree/bindings/sound/atmel-i2s.txt|  43 ++
 sound/soc/atmel/Kconfig|  10 +
 sound/soc/atmel/Makefile   |   2 +
 sound/soc/atmel/atmel-i2s.c| 760 +
 4 files changed, 815 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/atmel-i2s.txt
 create mode 100644 sound/soc/atmel/atmel-i2s.c

-- 
1.8.2.2

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


Re: [PATCH linux-next 0/4] mtd: spi-nor: fix Quad SPI memory support

2015-09-28 Thread Cyrille Pitchen
Hi all,

are there other works in progress to enhance the QSPI support inside the
spi-nor framework?
Do you have any suggestion about what should be done and how to do it?
Is there any discussion on this topic? If so, I would be interested in taking
part of it so I could synchronize my work with other developers' efforts.

Brian, Mark, Marek, with this series I've removed the Atmel QSPI controller
driver to focus only on the common spi-nor framework. I will send a dedicated
series later for the Atmel QSPI controller once we all agree on an update of
the framework API to add support to other QSPI memory manufacturers such as
Micron or Macronix.

Currently, it looks like the spi-nor framework only works with Spansion
memories. For instance, without the patches of this series, I can't use the
Micron n25q128a13 embedded on sama5d2 xplained boards.
So I hope we will find a way to make it work!

Best Regards,

Cyrille

Le 18/09/2015 17:49, Cyrille Pitchen a écrit :
> Hi all,
> 
> this series of patches fixes the QSPI support mostly for Micron and
> Macronix memories. There are also some updates for Spansion memories.
> There are also many comments to explain the implementation choices based
> on the datasheets from memory manufacturers.
> 
> The series was backported to a at91-4.1 kernel then tested on a sama5d2
> xplained board, which embeds a at25df321a memory on a SPI controller and
> a Micron n25q128a13 QSPI memory on the new Atmel QSPI controller.
> 
> The at25 memory was used to check non regression on the m25p80 driver
> whereas the Micron memory was used to test the fixes of the spi-nor
> framework. The driver for the Atmel QSPI controller will be sent in a
> dedicated series.
> 
> Best Regards,
> 
> Cyrille
> 
> Cyrille Pitchen (4):
>   mtd: spi-nor: remove unused read_xfer/write_xfer hooks
>   mtd: spi-nor: properly detect the memory when it boots in Quad or Dual
> mode
>   mtd: spi-nor: fix Quad SPI mode support for Spansion, Micron and
> Macronix
>   mtd: m25p80: add support of dual and quad spi protocols to all
> commands
> 
>  drivers/mtd/devices/m25p80.c  | 254 ++---
>  drivers/mtd/spi-nor/spi-nor.c | 811 
> --
>  include/linux/mtd/spi-nor.h   |  69 ++--
>  3 files changed, 954 insertions(+), 180 deletions(-)
> 

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


[PATCH 2/2] ASoC: atmel-i2s: add driver for the new Atmel I2S controller

2015-09-28 Thread Cyrille Pitchen
This patch adds support for the Atmel I2S controller embedded into
sama5d2x SoCs.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 sound/soc/atmel/Kconfig |  10 +
 sound/soc/atmel/Makefile|   2 +
 sound/soc/atmel/atmel-i2s.c | 760 
 3 files changed, 772 insertions(+)
 create mode 100644 sound/soc/atmel/atmel-i2s.c

diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 1489cd461aec..c026c207a386 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -30,6 +30,16 @@ config SND_ATMEL_SOC_SSC
default y if SND_ATMEL_SOC_SSC_DMA=y || SND_ATMEL_SOC_SSC_PDC=y
default m if SND_ATMEL_SOC_SSC_DMA=m || SND_ATMEL_SOC_SSC_PDC=m
 
+config SND_ATMEL_SOC_I2S
+   tristate "SoC Audio support for the Atmel I2S module"
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   select REGMAP_MMIO
+   depends on OF && (ARCH_AT91 || COMPILE_TEST)
+   help
+ Say Y or M if you want to add support for codecs attached to
+ the Atmel I2S interface. You will also need
+ to select the audio interfaces to support below.
+
 config SND_AT91_SOC_SAM9G20_WM8731
tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation 
board"
depends on ARCH_AT91 || COMPILE_TEST
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index b327e5cc8de3..4d960464aecb 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -2,10 +2,12 @@
 snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o
 snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
 snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
+snd-soc-atmel-i2s-objs := atmel-i2s.o
 
 obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o
 obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o
 obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
+obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o
 
 # AT91 Machine Support
 snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c
new file mode 100644
index ..7d44ac4e6ac9
--- /dev/null
+++ b/sound/soc/atmel/atmel-i2s.c
@@ -0,0 +1,760 @@
+/*
+ * Driver for Atmel I2S controller
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen <cyrille.pitc...@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ATMEL_I2SC_MAX_TDM_CHANNELS8
+
+/*
+ *  I2S Controller Register map 
+ */
+#define ATMEL_I2SC_CR  0x  /* Control Register */
+#define ATMEL_I2SC_MR  0x0004  /* Mode Register */
+#define ATMEL_I2SC_SR  0x0008  /* Status Register */
+#define ATMEL_I2SC_SCR 0x000c  /* Status Clear Register */
+#define ATMEL_I2SC_SSR 0x0010  /* Status Set Register */
+#define ATMEL_I2SC_IER 0x0014  /* Interrupt Enable Register */
+#define ATMEL_I2SC_IDR 0x0018  /* Interrupt Disable Register */
+#define ATMEL_I2SC_IMR 0x001c  /* Interrupt Mask Register */
+#define ATMEL_I2SC_RHR 0x0020  /* Receiver Holding Register */
+#define ATMEL_I2SC_THR 0x0024  /* Transmitter Holding Register */
+#define ATMEL_I2SC_VERSION 0x0028  /* Version Register */
+
+
+/*
+ *  Control Register (Write-only) 
+ */
+#define ATMEL_I2SC_CR_RXEN BIT(0)  /* Receiver Enable */
+#define ATMEL_I2SC_CR_RXDISBIT(1)  /* Receiver Disable */
+#define ATMEL_I2SC_CR_CKEN BIT(2)  /* Clock Enable */
+#define ATMEL_I2SC_CR_CKDISBIT(3)  /* Clock Disable */
+#define ATMEL_I2SC_CR_TXEN BIT(4)  /* Transmitter Enable */
+#define ATMEL_I2SC_CR_TXDISBIT(5)  /* Transmitter Disable */
+#define ATMEL_I2SC_CR_SWRSTBIT(7)  /* Software Reset */
+
+
+/*
+ *  Mode Register (Read/Write) 
+ */
+#define ATMEL_I2SC_MR_MODE_MASKGENMASK(0, 0)
+#define ATMEL_I2SC_MR_MODE_SLAVE   (0 << 0)
+#define ATMEL_I2SC_MR_MODE_MASTER  (1 << 0)
+
+#define ATMEL_I2SC_MR_DATALENGTH_MASK  GENMASK(4, 2)
+#define ATMEL_I2SC_MR_DATALENGTH_32_BITS   (0 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_24_BITS   (1 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_20_BITS   (2 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_18_BITS 

[PATCH 1/2] ASoC: atmel-i2s: add DT bindings for I2S controller

2015-09-28 Thread Cyrille Pitchen
This patch adds DT bindings for the new Atmel I2S controller embedded
inside sama5d2x SoCs.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 .../devicetree/bindings/sound/atmel-i2s.txt| 43 ++
 1 file changed, 43 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/atmel-i2s.txt

diff --git a/Documentation/devicetree/bindings/sound/atmel-i2s.txt 
b/Documentation/devicetree/bindings/sound/atmel-i2s.txt
new file mode 100644
index ..83bc6b9070bf
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/atmel-i2s.txt
@@ -0,0 +1,43 @@
+* Atmel I2S controller
+
+Required properties:
+- compatible: Should be "atmel,sama5d2-i2s".
+- reg:Should be the physical base address of the controller and the
+  length of memory mapped region.
+- interrupts: Should contain the interrupt for the controller.
+- dmas:   Should be a list of pairs of DMA controller phandle and 
flags.
+- dma-names:  Should be a list of DMA channel name among "rx", "tx" or
+  "rx-tx".
+- clocks: Should be a list of phandles of clocks used by the controller
+  (1).
+- clock-names:Should be a list matching the clocks phandles list:
+  - "pclk" (peripheral clock) Required.
+  - "gclk" (generated clock) Optional (1).
+  - "aclk" (Audio PLL clock) Optional (1).
+
+Optional properties:
+- pinctrl-0:  Should specify pin control groups used for this controller.
+- princtrl-names: Should contain only one value - "default".
+
+
+(1) : Only the peripheral clock is required. The generated clock and the Audio
+  PLL clock are optional and should only be set together.
+
+Example:
+
+   i2s@f805 {
+   compatible = "atmel,sama5d2-i2s";
+   reg = <0xf805 0x300>;
+   interrupts = <54 IRQ_TYPE_LEVEL_HIGH 7>;
+   dmas = <
+   (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+AT91_XDMAC_DT_PERID(31))>,
+  <
+   (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+AT91_XDMAC_DT_PERID(32))>;
+   dma-names = "tx", "rx";
+   clocks = <_clk>, <_gclk>, <_pll_pmc>;
+   clock-names = "pclk", "gclk", "aclk";
+   pinctrl-names = "default";
+   pinctrl-0 = <_i2s0_default>;
+   };
-- 
1.8.2.2

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


[PATCH linux-next v11 3/3] mfd: atmel-flexcom: add a driver for Atmel Flexible Serial Communication Unit

2015-09-28 Thread Cyrille Pitchen
This driver supports the new Atmel Flexcom. The Flexcom is a wrapper which
integrates one SPI controller, one I2C controller and one USART. Only one
function can be enabled at a time. This driver selects the function once
for all, when the Flexcom is probed, according to the value of the new
"atmel,flexcom-mode" device tree property.

This driver has chosen to present the Flexcom to the system as a MFD so
the implementation is seamless for the existing Atmel SPI, I2C and USART
drivers.

Also the Flexcom embeds FIFOs: the latest patches of the SPI, I2C and
USART drivers take advantage of this new feature.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
Acked-by: Boris Brezillon <boris.brezil...@free-electrons.com>
Acked-by: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.fe...@atmel.com>
---
 drivers/mfd/Kconfig |  11 +
 drivers/mfd/Makefile|   1 +
 drivers/mfd/atmel-flexcom.c | 104 
 3 files changed, 116 insertions(+)
 create mode 100644 drivers/mfd/atmel-flexcom.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 99d63675f073..87e84e7c71da 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -60,6 +60,17 @@ config MFD_AAT2870_CORE
  additional drivers must be enabled in order to use the
  functionality of the device.
 
+config MFD_ATMEL_FLEXCOM
+   tristate "Atmel Flexcom (Flexible Serial Communication Unit)"
+   select MFD_CORE
+   depends on OF
+   help
+ Select this to get support for Atmel Flexcom. This is a wrapper
+ which embeds a SPI controller, a I2C controller and a USART. Only
+ one function can be used at a time. The choice is done at boot time
+ by the probe function of this MFD driver according to a device tree
+ property.
+
 config MFD_ATMEL_HLCDC
tristate "Atmel HLCDC (High-end LCD Controller)"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d6c21e3c409f..a8b76b81b467 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -164,6 +164,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
 obj-$(CONFIG_TPS65911_COMPARATOR)  += tps65911-comparator.o
 obj-$(CONFIG_MFD_TPS65090) += tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
+obj-$(CONFIG_MFD_ATMEL_FLEXCOM)+= atmel-flexcom.o
 obj-$(CONFIG_MFD_ATMEL_HLCDC)  += atmel-hlcdc.o
 obj-$(CONFIG_MFD_INTEL_LPSS)   += intel-lpss.o
 obj-$(CONFIG_MFD_INTEL_LPSS_PCI)   += intel-lpss-pci.o
diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
new file mode 100644
index ..e8e67be6b493
--- /dev/null
+++ b/drivers/mfd/atmel-flexcom.c
@@ -0,0 +1,104 @@
+/*
+ * Driver for Atmel Flexcom
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen <cyrille.pitc...@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* I/O register offsets */
+#define FLEX_MR0x0 /* Mode Register */
+#define FLEX_VERSION   0xfc/* Version Register */
+
+/* Mode Register bit fields */
+#define FLEX_MR_OPMODE_OFFSET  (0)  /* Operating Mode */
+#define FLEX_MR_OPMODE_MASK(0x3 << FLEX_MR_OPMODE_OFFSET)
+#define FLEX_MR_OPMODE(opmode) (((opmode) << FLEX_MR_OPMODE_OFFSET) &  \
+FLEX_MR_OPMODE_MASK)
+
+
+static int atmel_flexcom_probe(struct platform_device *pdev)
+{
+   struct device_node *np = pdev->dev.of_node;
+   struct clk *clk;
+   struct resource *res;
+   void __iomem *base;
+   u32 opmode;
+   int err;
+
+   err = of_property_read_u32(np, "atmel,flexcom-mode", );
+   if (err)
+   return err;
+
+   if (opmode < ATMEL_FLEXCOM_MODE_USART ||
+   opmode > ATMEL_FLEXCOM_MODE_TWI)
+   return -EINVAL;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(base))
+   return PTR_ERR(base);
+
+   clk = devm_clk_get(>dev, NULL);
+   if (IS_ERR(clk))
+   return PTR_ERR(clk);
+
+   err = clk_prepare_enable(clk);
+   if (err)
+ 

[PATCH linux-next v11 1/3] mfd: atmel-flexcom: create include file with macros used by DT bindings

2015-09-28 Thread Cyrille Pitchen
This patch defines some macros to be used as value for the
"atmel,flexcom-mode" DT property. This value is then written into
the Operating Mode (OPMODE) bit field of the Flexcom Mode Register.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
Acked-by: Nicolas Ferre <nicolas.fe...@atmel.com>
---
 include/dt-bindings/mfd/atmel-flexcom.h | 26 ++
 1 file changed, 26 insertions(+)
 create mode 100644 include/dt-bindings/mfd/atmel-flexcom.h

diff --git a/include/dt-bindings/mfd/atmel-flexcom.h 
b/include/dt-bindings/mfd/atmel-flexcom.h
new file mode 100644
index ..a266fe4ee945
--- /dev/null
+++ b/include/dt-bindings/mfd/atmel-flexcom.h
@@ -0,0 +1,26 @@
+/*
+ * This header provides macros for Atmel Flexcom DT bindings.
+ *
+ * Copyright (C) 2015 Cyrille Pitchen <cyrille.pitc...@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DT_BINDINGS_ATMEL_FLEXCOM_H__
+#define __DT_BINDINGS_ATMEL_FLEXCOM_H__
+
+#define ATMEL_FLEXCOM_MODE_USART   1
+#define ATMEL_FLEXCOM_MODE_SPI 2
+#define ATMEL_FLEXCOM_MODE_TWI 3
+
+#endif /* __DT_BINDINGS_ATMEL_FLEXCOM_H__ */
-- 
1.8.2.2

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


[PATCH linux-next v11 2/3] mfd: devicetree: add bindings for Atmel Flexcom

2015-09-28 Thread Cyrille Pitchen
This patch documents the DT bindings for the Atmel Flexcom which will be
introduced by sama5d2x SoCs. These bindings will be used by the actual
Flexcom driver to be sent in another patch.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
Acked-by: Boris Brezillon <boris.brezil...@free-electrons.com>
Acked-by: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.fe...@atmel.com>
---
 .../devicetree/bindings/mfd/atmel-flexcom.txt  | 63 ++
 1 file changed, 63 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt

diff --git a/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt 
b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
new file mode 100644
index ..692300117c64
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
@@ -0,0 +1,63 @@
+* Device tree bindings for Atmel Flexcom (Flexible Serial Communication Unit)
+
+The Atmel Flexcom is just a wrapper which embeds a SPI controller, an I2C
+controller and an USART. Only one function can be used at a time and is chosen
+at boot time according to the device tree.
+
+Required properties:
+- compatible:  Should be "atmel,sama5d2-flexcom"
+- reg: Should be the offset/length value for Flexcom dedicated
+   I/O registers (without USART, TWI or SPI registers).
+- clocks:  Should be the Flexcom peripheral clock from PMC.
+- #address-cells:  Should be <1>
+- #size-cells: Should be <1>
+- ranges:  Should be one range for the full I/O register region
+   (including USART, TWI and SPI registers).
+- atmel,flexcom-mode:  Should be one of the following values:
+   - <1> for USART
+   - <2> for SPI
+   - <3> for I2C
+
+Required child:
+A single available child device of type matching the "atmel,flexcom-mode"
+property.
+
+The phandle provided by the clocks property of the child is the same as one for
+the Flexcom parent.
+
+For other properties, please refer to the documentations of the respective
+device:
+- ../serial/atmel-usart.txt
+- ../spi/spi_atmel.txt
+- ../i2c/i2c-at91.txt
+
+Example:
+
+flexcom@f8034000 {
+   compatible = "atmel,sama5d2-flexcom";
+   reg = <0xf8034000 0x200>;
+   clocks = <_clk>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0x0 0xf8034000 0x800>;
+   atmel,flexcom-mode = <2>;
+
+   spi@400 {
+   compatible = "atmel,at91rm9200-spi";
+   reg = <0x400 0x200>;
+   interrupts = <19 IRQ_TYPE_LEVEL_HIGH 7>;
+   pinctrl-names = "default";
+   pinctrl-0 = <_flx0_default>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   clocks = <_clk>;
+   clock-names = "spi_clk";
+   atmel,fifo-size = <32>;
+
+   mtd_dataflash@0 {
+   compatible = "atmel,at25f512b";
+   reg = <0>;
+   spi-max-frequency = <2000>;
+   };
+   };
+};
-- 
1.8.2.2

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


[PATCH linux-next v11 0/3] mfd: flexcom: add a driver for Flexcom

2015-09-28 Thread Cyrille Pitchen
This series of patches a support to the Atmel Flexcom, a wrapper which
integrates an USART, a SPI controller and a TWI controller. Only one
peripheral can be used at a time. The active function is selected though
the Flexcom Mode Register.


ChangeLog

v11:
- replace "GPLv2 only" by a proper license statement  in
  "include/dt-bindings/mfd/atmel-flexcom.h" as suggested by Lee Jones.
- remove usage of Linux specific macros for the values of the
  "atmel,flexcom-mode" property in the DT bindings documentation.
- fix typo and reword some parts of the DT bindings documentation.

v10:
- add Acked-by from Nicolas Ferre

v9:
- go back to v5 (use the new "atmel,flexcom-mode" DT property).
- fix the name of the spi node in the DT example: from spi@f8034400 to
  spi@400
- align the fields of the struct platform_driver atmel_flexcom_driver as
  suggested by Lee Jones.

v8:
- fix the name of the spi node in the DT example: from spi@f8034400 to
  spi@2,0
- use the return code of op_property_read_u32_index() instead of -EINVAL
  to report error.
- add Acked-by from Nicolas Ferre

v7:
- read the operating mode from the very first u32 of the reg property from
  the first available child node (should be unique).
- update the DT bindings documentation accordingly.

v6:
- select the operating mode according to the "compatible" DT property of
  the first available child node (should be unique).
- remove the "atmel,flexcom-mode" DT property so the need of a header file
  defining macros for the possible values of this deprecated property.

v5:
- create a header file containing macros used by DT bindings
- use numeric constants instead of strings to select the Flexcom mode
- change the license to "GPL v2"
- update the DT binding documentation to make it more readable and add
  references to USART, SPI and I2C DT binding documentations. remove the
  useless label in the Example section.
- change the register prefix from FX_ to FLEX_ to match the Flexcom
  programmer datasheet.
- rename some variables to make them more understandable.

v4:
- check clk_prepare_enable() return code in atmel_flexcom_probe()
- add a commit message to the DT binding patch

v3:
- remove MODULE_ALIAS()
- add Acked-by from Boris Brezillon and Alexandre Belloni

v2:
- enhance the documentation of DT bindings and change the way the "ranges"
  property is used.
- replace __raw_readl() and __raw_writel() by readl() and writel().
- change the module license to "GPL" for v2 or later
- print the selected flexcom mode after the hardware version

Cyrille Pitchen (3):
  mfd: atmel-flexcom: create include file with macros used by DT
bindings
  mfd: devicetree: add bindings for Atmel Flexcom
  mfd: atmel-flexcom: add a driver for Atmel Flexible Serial
Communication Unit

 .../devicetree/bindings/mfd/atmel-flexcom.txt  |  63 +
 drivers/mfd/Kconfig|  11 +++
 drivers/mfd/Makefile   |   1 +
 drivers/mfd/atmel-flexcom.c| 104 +
 include/dt-bindings/mfd/atmel-flexcom.h|  26 ++
 5 files changed, 205 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
 create mode 100644 drivers/mfd/atmel-flexcom.c
 create mode 100644 include/dt-bindings/mfd/atmel-flexcom.h

-- 
1.8.2.2

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


[PATCH linux-next v10 2/3] mfd: devicetree: add bindings for Atmel Flexcom

2015-09-24 Thread Cyrille Pitchen
This patch documents the DT bindings for the Atmel Flexcom which will be
introduced by sama5d2x SoCs. These bindings will be used by the actual
Flexcom driver to be sent in another patch.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
Acked-by: Boris Brezillon <boris.brezil...@free-electrons.com>
Acked-by: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.fe...@atmel.com>
---
 .../devicetree/bindings/mfd/atmel-flexcom.txt  | 67 ++
 1 file changed, 67 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt

diff --git a/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt 
b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
new file mode 100644
index ..fc3511e41542
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
@@ -0,0 +1,67 @@
+* Device tree bindings for Atmel Flexcom (Flexible Serial Communication Unit)
+
+The Atmel Flexcom is just a wrapper which embeds a SPI controller, an I2C
+controller and an USART. Only one function can be used at a time and is chosen
+at boot time according to the device tree.
+
+Required properties:
+- compatible:  Should be "atmel,sama5d2-flexcom"
+- reg: Should be the offset/length value for Flexcom dedicated
+   I/O registers (without USART, TWI or SPI registers).
+- clocks:  Should be the Flexcom peripheral clock from PMC.
+- #address-cells:  Should be <1>
+- #size-cells: Should be <1>
+- ranges:  Should be one range for the full I/O register region
+   (including USART, TWI and SPI registers).
+- atmel,flexcom-mode:  Should be one of the 3 following macros as defined in
+   include/dt-bindings/mfd/atmel-flexcom.h:
+   - ATMEL_FLEXCOM_MODE_USART for USART
+   - ATMEL_FLEXCOM_MODE_SPI for SPI
+   - ATMEL_FLEXCOM_MODE_TWI for I2C
+
+Required child:
+a single child device of type matching the "atmel,flexcom-mode" property.
+
+The reg property of this child should be:
+- <0x200 0x200> for USART
+- <0x400 0x200> for SPI
+- <0x600 0x200> for I2C
+
+The phandle provided by the clocks property of the child is the same as one for
+the Flexcom parent.
+
+Other properties remain unchanged. See documentation of the respective device:
+- ../serial/atmel-usart.txt
+- ../spi/spi_atmel.txt
+- ../i2c/i2c-at91.txt
+
+Example:
+
+flexcom@f8034000 {
+   compatible = "atmel,sama5d2-flexcom";
+   reg = <0xf8034000 0x200>;
+   clocks = <_clk>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0x0 0xf8034000 0x800>;
+   atmel,flexcom-mode = ;
+
+   spi@400 {
+   compatible = "atmel,at91rm9200-spi";
+   reg = <0x400 0x200>;
+   interrupts = <19 IRQ_TYPE_LEVEL_HIGH 7>;
+   pinctrl-names = "default";
+   pinctrl-0 = <_flx0_default>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   clocks = <_clk>;
+   clock-names = "spi_clk";
+   atmel,fifo-size = <32>;
+
+   mtd_dataflash@0 {
+   compatible = "atmel,at25f512b";
+   reg = <0>;
+   spi-max-frequency = <2000>;
+   };
+   };
+};
-- 
1.8.2.2

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


[PATCH linux-next v10 0/3] mfd: flexcom: add a driver for Flexcom

2015-09-24 Thread Cyrille Pitchen
This series of patches a support to the Atmel Flexcom, a wrapper which
integrates an USART, a SPI controller and a TWI controller. Only one
peripheral can be used at a time. The active function is selected though
the Flexcom Mode Register


ChangeLog

v10:
- add Acked-by from Nicolas Ferre

v9:
- go back to v5 (use the new "atmel,flexcom-mode" DT property).
- fix the name of the spi node in the DT example: from spi@f8034400 to
  spi@400
- align the fields of the struct platform_driver atmel_flexcom_driver as
  suggested by Lee Jones.

v8:
- fix the name of the spi node in the DT example: from spi@f8034400 to
  spi@2,0
- use the return code of op_property_read_u32_index() instead of -EINVAL
  to report error.
- add Acked-by from Nicolas Ferre

v7:
- read the operating mode from the very first u32 of the reg property from
  the first available child node (should be unique).
- update the DT bindings documentation accordingly.

v6:
- select the operating mode according to the "compatible" DT property of
  the first available child node (should be unique).
- remove the "atmel,flexcom-mode" DT property so the need of a header file
  defining macros for the possible values of this deprecated property.

v5:
- create a header file containing macros used by DT bindings
- use numeric constants instead of strings to select the Flexcom mode
- change the license to "GPL v2"
- update the DT binding documentation to make it more readable and add
  references to USART, SPI and I2C DT binding documentations. remove the
  useless label in the Example section.
- change the register prefix from FX_ to FLEX_ to match the Flexcom
  programmer datasheet.
- rename some variables to make them more understandable.

v4:
- check clk_prepare_enable() return code in atmel_flexcom_probe()
- add a commit message to the DT binding patch

v3:
- remove MODULE_ALIAS()
- add Acked-by from Boris Brezillon and Alexandre Belloni

v2:
- enhance the documentation of DT bindings and change the way the "ranges"
  property is used.
- replace __raw_readl() and __raw_writel() by readl() and writel().
- change the module license to "GPL" for v2 or later
- print the selected flexcom mode after the hardware version

Cyrille Pitchen (3):
  mfd: atmel-flexcom: create include file with macros used by DT
bindings
  mfd: devicetree: add bindings for Atmel Flexcom
  mfd: atmel-flexcom: add a driver for Atmel Flexible Serial
Communication Unit

 .../devicetree/bindings/mfd/atmel-flexcom.txt  |  67 +
 drivers/mfd/Kconfig|  11 +++
 drivers/mfd/Makefile   |   1 +
 drivers/mfd/atmel-flexcom.c| 104 +
 include/dt-bindings/mfd/atmel-flexcom.h|  16 
 5 files changed, 199 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
 create mode 100644 drivers/mfd/atmel-flexcom.c
 create mode 100644 include/dt-bindings/mfd/atmel-flexcom.h

-- 
1.8.2.2

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


[PATCH linux-next v10 1/3] mfd: atmel-flexcom: create include file with macros used by DT bindings

2015-09-24 Thread Cyrille Pitchen
This patch defines some macros to be used as value for the
"atmel,flexcom-mode" DT property. This value is then written into
the Operating Mode (OPMODE) bit field of the Flexcom Mode Register.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
Acked-by: Nicolas Ferre <nicolas.fe...@atmel.com>
---
 include/dt-bindings/mfd/atmel-flexcom.h | 16 
 1 file changed, 16 insertions(+)
 create mode 100644 include/dt-bindings/mfd/atmel-flexcom.h

diff --git a/include/dt-bindings/mfd/atmel-flexcom.h 
b/include/dt-bindings/mfd/atmel-flexcom.h
new file mode 100644
index ..6728f2851b4d
--- /dev/null
+++ b/include/dt-bindings/mfd/atmel-flexcom.h
@@ -0,0 +1,16 @@
+/*
+ * This header provides macros for Atmel Flexcom DT bindings.
+ *
+ * Copyright (C) 2015 Cyrille Pitchen <cyrille.pitc...@atmel.com>
+ *
+ * GPLv2 only
+ */
+
+#ifndef __DT_BINDINGS_ATMEL_FLEXCOM_H__
+#define __DT_BINDINGS_ATMEL_FLEXCOM_H__
+
+#define ATMEL_FLEXCOM_MODE_USART   1
+#define ATMEL_FLEXCOM_MODE_SPI 2
+#define ATMEL_FLEXCOM_MODE_TWI 3
+
+#endif /* __DT_BINDINGS_ATMEL_FLEXCOM_H__ */
-- 
1.8.2.2

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


[PATCH linux-next v10 3/3] mfd: atmel-flexcom: add a driver for Atmel Flexible Serial Communication Unit

2015-09-24 Thread Cyrille Pitchen
This driver supports the new Atmel Flexcom. The Flexcom is a wrapper which
integrates one SPI controller, one I2C controller and one USART. Only one
function can be enabled at a time. This driver selects the function once
for all, when the Flexcom is probed, according to the value of the new
"atmel,flexcom-mode" device tree property.

This driver has chosen to present the Flexcom to the system as a MFD so
the implementation is seamless for the existing Atmel SPI, I2C and USART
drivers.

Also the Flexcom embeds FIFOs: the latest patches of the SPI, I2C and
USART drivers take advantage of this new feature.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
Acked-by: Boris Brezillon <boris.brezil...@free-electrons.com>
Acked-by: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.fe...@atmel.com>
---
 drivers/mfd/Kconfig |  11 +
 drivers/mfd/Makefile|   1 +
 drivers/mfd/atmel-flexcom.c | 104 
 3 files changed, 116 insertions(+)
 create mode 100644 drivers/mfd/atmel-flexcom.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 99d63675f073..87e84e7c71da 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -60,6 +60,17 @@ config MFD_AAT2870_CORE
  additional drivers must be enabled in order to use the
  functionality of the device.
 
+config MFD_ATMEL_FLEXCOM
+   tristate "Atmel Flexcom (Flexible Serial Communication Unit)"
+   select MFD_CORE
+   depends on OF
+   help
+ Select this to get support for Atmel Flexcom. This is a wrapper
+ which embeds a SPI controller, a I2C controller and a USART. Only
+ one function can be used at a time. The choice is done at boot time
+ by the probe function of this MFD driver according to a device tree
+ property.
+
 config MFD_ATMEL_HLCDC
tristate "Atmel HLCDC (High-end LCD Controller)"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d6c21e3c409f..a8b76b81b467 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -164,6 +164,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
 obj-$(CONFIG_TPS65911_COMPARATOR)  += tps65911-comparator.o
 obj-$(CONFIG_MFD_TPS65090) += tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
+obj-$(CONFIG_MFD_ATMEL_FLEXCOM)+= atmel-flexcom.o
 obj-$(CONFIG_MFD_ATMEL_HLCDC)  += atmel-hlcdc.o
 obj-$(CONFIG_MFD_INTEL_LPSS)   += intel-lpss.o
 obj-$(CONFIG_MFD_INTEL_LPSS_PCI)   += intel-lpss-pci.o
diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
new file mode 100644
index ..e8e67be6b493
--- /dev/null
+++ b/drivers/mfd/atmel-flexcom.c
@@ -0,0 +1,104 @@
+/*
+ * Driver for Atmel Flexcom
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen <cyrille.pitc...@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* I/O register offsets */
+#define FLEX_MR0x0 /* Mode Register */
+#define FLEX_VERSION   0xfc/* Version Register */
+
+/* Mode Register bit fields */
+#define FLEX_MR_OPMODE_OFFSET  (0)  /* Operating Mode */
+#define FLEX_MR_OPMODE_MASK(0x3 << FLEX_MR_OPMODE_OFFSET)
+#define FLEX_MR_OPMODE(opmode) (((opmode) << FLEX_MR_OPMODE_OFFSET) &  \
+FLEX_MR_OPMODE_MASK)
+
+
+static int atmel_flexcom_probe(struct platform_device *pdev)
+{
+   struct device_node *np = pdev->dev.of_node;
+   struct clk *clk;
+   struct resource *res;
+   void __iomem *base;
+   u32 opmode;
+   int err;
+
+   err = of_property_read_u32(np, "atmel,flexcom-mode", );
+   if (err)
+   return err;
+
+   if (opmode < ATMEL_FLEXCOM_MODE_USART ||
+   opmode > ATMEL_FLEXCOM_MODE_TWI)
+   return -EINVAL;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(base))
+   return PTR_ERR(base);
+
+   clk = devm_clk_get(>dev, NULL);
+   if (IS_ERR(clk))
+   return PTR_ERR(clk);
+
+   err = clk_prepare_enable(clk);
+   if (err)
+ 

Re: [PATCH linux-next v9 2/3] mfd: devicetree: add bindings for Atmel Flexcom

2015-09-21 Thread Cyrille Pitchen
Hi Rob,

Le 10/09/2015 02:06, Rob Herring a écrit :
> On 09/09/2015 10:45 AM, Cyrille Pitchen wrote:
>> Hi Rob,
>>
>> Le 09/09/2015 01:40, Rob Herring a écrit :
>>> On 09/01/2015 09:46 AM, Cyrille Pitchen wrote:
>>>> This patch documents the DT bindings for the Atmel Flexcom which will be
>>>> introduced by sama5d2x SoCs. These bindings will be used by the actual
>>>> Flexcom driver to be sent in another patch.
>>>>
>>>> Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
>>>> Acked-by: Boris Brezillon <boris.brezil...@free-electrons.com>
>>>> Acked-by: Alexandre Belloni <alexandre.bell...@free-electrons.com>
>>>
>>> A few comments, but in general looks fine.
>>>
>>>> ---
>>>>  .../devicetree/bindings/mfd/atmel-flexcom.txt  | 67 
>>>> ++
>>>>  1 file changed, 67 insertions(+)
>>>>  create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt 
>>>> b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
>>>> new file mode 100644
>>>> index ..fc3511e41542
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
>>>> @@ -0,0 +1,67 @@
>>>> +* Device tree bindings for Atmel Flexcom (Flexible Serial Communication 
>>>> Unit)
>>>> +
>>>> +The Atmel Flexcom is just a wrapper which embeds a SPI controller, an I2C
>>>> +controller and an USART. Only one function can be used at a time and is 
>>>> chosen
>>>> +at boot time according to the device tree.
>>>
>>> Doesn't the board design choose (unless pins go to a header)?
>>>
>>
>> The function may be chosen once for all by the board design but if we take 
>> the
>> sama5d2 xplained board as an example, most Flexcoms output their pins to
>> headers.
>>
>>>> +
>>>> +Required properties:
>>>> +- compatible: Should be "atmel,sama5d2-flexcom"
>>>> +- reg:Should be the offset/length value for Flexcom 
>>>> dedicated
>>>> +  I/O registers (without USART, TWI or SPI registers).
>>>> +- clocks: Should be the Flexcom peripheral clock from PMC.
>>>> +- #address-cells: Should be <1>
>>>> +- #size-cells:Should be <1>
>>>> +- ranges: Should be one range for the full I/O register region
>>>> +  (including USART, TWI and SPI registers).
>>>> +- atmel,flexcom-mode: Should be one of the 3 following macros as 
>>>> defined in
>>>> +  include/dt-bindings/mfd/atmel-flexcom.h:
>>>> +  - ATMEL_FLEXCOM_MODE_USART for USART
>>>> +  - ATMEL_FLEXCOM_MODE_SPI for SPI
>>>> +  - ATMEL_FLEXCOM_MODE_TWI for I2C
>>>> +
>>>> +Required child:
>>>> +a single child device of type matching the "atmel,flexcom-mode" property.
>>>
>>> Okay, but why not allow all children and use "status"?
>>>
>>
>> That is exactly what was proposed in v6 of this series: allow more than one
>> child so possibly all children but only one "available" child (status = 
>> "okay").
>>
>> The Flexocm driver still needs to find out the type of device of this
>> available child to know which function is to be enabled (USART, I2C or SPI).
>> So the "compatible" attribute was parsed using strstr() to search on of the
>> patterns "usart", "spi" or "i2c".
>>
>> However the use of strstr() was discussed to know whether the driver should
>> looks for a partial or an exact match of the "compatible" string.
>> An exact match would require to keep the Flexcom driver synchonized with the
>> 3 other drivers every time one of them introduces a new compatibility string,
>> which whould have made every driver more difficult to maintain by creating a
>> useless dependency.
>> So this implementation relying on the "compatible" attribute was abandoned.
>>
>> To sum up, no other reliable (and simple) means to guess/extact the device
>> type from its DT node was found so we got back to the "atmel,flexcom-mode"
>> property.
> 
> I wasn't thinking removing this property. If the mode is configured by
> the bootloader, then you want to make updates to the configuration as
> simple as possible. Updating atmel,flexcom-mode and status for the
> children would be much more simple than creating the whole child node.
> If that's not a valid usecase, then never mind.
> 
> Rob
> 

The Flexcom driver calls of_platform_populate(), so yes it's allowed and
supported to put the 3 children in the DT as long as only one is available.

Should I update the documentation to deal with optional children or leave it
as it is?

Best Regards,

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


[PATCH linux-next 2/4] mtd: spi-nor: properly detect the memory when it boots in Quad or Dual mode

2015-09-18 Thread Cyrille Pitchen
The quad (or dual) mode of a spi-nor memory may be enabled at boot time by
non-volatile bits in some setting register. Also such a mode may have
already been enabled at early stage by some boot loader.

Hence, we should not guess the spi-nor memory is always configured for the
regular SPI 1-1-1 protocol.

Micron and Macronix memories, once their Quad (or dual for Micron) mode
enabled, no longer process the regular JEDEC Read ID (0x9f) command but
instead reply to a new command: JEDEC Read ID Multiple I/O (0xaf).
Besides, in Quad mode both memory manufacturers expect ALL commands to
use the SPI 4-4-4 protocol. For Micron memories, enabling their Dual mode
implies to use the SPI 2-2-2 protocol for ALL commands.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 52 +++
 include/linux/mtd/spi-nor.h   | 23 +--
 2 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 8818d4325d20..b857e9be2026 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -61,6 +61,11 @@ struct flash_info {
 
 #define JEDEC_MFR(info)((info)->id[0])
 
+struct read_id_config {
+   enum read_mode  mode;
+   enum spi_protocol   proto;
+};
+
 static const struct flash_info *spi_nor_match_id(const char *name);
 
 /*
@@ -701,11 +706,16 @@ static const struct flash_info spi_nor_ids[] = {
{ },
 };
 
-static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
+static const struct flash_info *spi_nor_read_id(struct spi_nor *nor,
+   enum read_mode mode)
 {
-   int tmp;
+   int i, tmp;
u8  id[SPI_NOR_MAX_ID_LEN];
const struct flash_info *info;
+   static const struct read_id_config configs[] = {
+   {SPI_NOR_QUAD, SPI_PROTO_4_4_4},
+   {SPI_NOR_DUAL, SPI_PROTO_2_2_2}
+   };
 
tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
if (tmp < 0) {
@@ -713,6 +723,34 @@ static const struct flash_info *spi_nor_read_id(struct 
spi_nor *nor)
return ERR_PTR(tmp);
}
 
+   /* Special case for Micron/Macronix qspi nor. */
+   if ((id[0] == 0xff && id[1] == 0xff && id[2] == 0xff) ||
+   (id[0] == 0x00 && id[1] == 0x00 && id[2] == 0x00))
+   for (i = 0; i < ARRAY_SIZE(configs); ++i) {
+   if (configs[i].mode != mode)
+   continue;
+
+   /* Set this protocol for all commands. */
+   nor->reg_proto = configs[i].proto;
+   nor->read_proto = configs[i].proto;
+   nor->write_proto = configs[i].proto;
+   nor->erase_proto = configs[i].proto;
+
+   /*
+* Multiple I/O Read ID only returns the Manufacturer ID
+* (1 byte) and the Device ID (2 bytes). So we reset the
+* remaining bytes.
+*/
+   memset(id, 0, sizeof(id));
+   tmp = nor->read_reg(nor, SPINOR_OP_MIO_RDID, id, 3);
+   if (tmp < 0) {
+   dev_dbg(nor->dev,
+   "error %d reading JEDEC ID Multi I/O\n",
+   tmp);
+   return ERR_PTR(tmp);
+   }
+   }
+
for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) {
info = _nor_ids[tmp];
if (info->id_len) {
@@ -1012,11 +1050,17 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
if (ret)
return ret;
 
+   /* Reset SPI protocol for all commands */
+   nor->erase_proto = SPI_PROTO_1_1_1;
+   nor->read_proto = SPI_PROTO_1_1_1;
+   nor->write_proto = SPI_PROTO_1_1_1;
+   nor->reg_proto = SPI_PROTO_1_1_1;
+
if (name)
info = spi_nor_match_id(name);
/* Try to auto-detect if chip name wasn't specified or not found */
if (!info)
-   info = spi_nor_read_id(nor);
+   info = spi_nor_read_id(nor, mode);
if (IS_ERR_OR_NULL(info))
return -ENOENT;
 
@@ -1027,7 +1071,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
if (name && info->id_len) {
const struct flash_info *jinfo;
 
-   jinfo = spi_nor_read_id(nor);
+   jinfo = spi_nor_read_id(nor, mode);
if (IS_ERR(jinfo)) {
return PTR_ERR(jinfo);
  

[PATCH linux-next 3/4] mtd: spi-nor: fix Quad SPI mode support for Spansion, Micron and Macronix

2015-09-18 Thread Cyrille Pitchen
This patch reworks the support of Quad and Dual SPI protocols for Micron,
Spansion and Macronix Quad/Dual capable memories. Indeed, in the best
case, only Spansion memories are correctly supported by the current
spi-nor framework.

1 - Micron:
When their Quad SPI mode is enabled, Micron spi-nor memories expect all
commands to use the SPI 4-4-4 protocol. Also when the Dual SPI mode is
enabled, all commands must use the SPI 2-2-2 protocol.

Before this patch, the spi-nor framework used to always enable the Quad
mode when the mode argument of spi_nor_scan() took the value SPI_NOR_QUAD.
That was not suited with drivers only supporting SPI 1-x-4 protocols but
not the 4-4-4 (e.g. the m25p80 driver). Also the SPI controller was not
notified about which SPI protocol to use to transfert command. We cannot
rely only on the op code: in Extended SPI mode the 0x6b command must  use
the SPI 1-1-4 protocol whereas in Quad SPi mode the SPI 4-4-4 protocol
must be use instead.

After this patch, the spi-nor framework uses the result of the
spi_nor_read_id() function to choose the right SPI protocol to be used.
If the reg_proto was set to SPI_PROTO_4_4_4, we already know that the Quad
SPI mode is already enabled and that the SPI controller supports the SPI
4-4-4 protocol (otherwise it would have fail to read the JEDEC ID with the
0xaf op code). For the very same reason, if the reg_proto was set to
SPI_PROTO_2_2_2, we already know that the Dual mode is already enabled and
that the SPI controller supports the SPI 2-2-2 protocol.
Otherwise we switch back to the Extended SPI protocol, which supports at
least the Fast Read commands:
- 1-1-1 (0x0b)
- Dual Output 1-1-2 (0x3b)
- Quad Output 1-1-4 (0x6b)

We also safely set the number of dummy cycles to 8 for Fast Read commands
through the Volatile Configuration Register (VCR): some drivers (m25p80)
or SPI controllers only support a number of dummy cycles multiple of 8.
This number may have previouly been set to an unsupported value by an
early bootloader or at reset thanks to the Non-Volatile Configuration
Register.

Finally the XIP bit is always set in the VCR to disable the Continuous
Read mode as we don't want to care about mode cycles.

2 - Macronix:
When the QPI mode is enabled, all commands must use the SPI 4-4-4 protocol
and only the 0xeb op code is supported for Fast Read commands.
Before this patch, the spi-nor framework used to force the QPI mode but
used the 0x6b op code for Fast Read commands when the SPI controller
claims to support Quad SPI mode.
This patch uses the result of spi_nor_read_id() to guess whether the QPI
mode is both enable and supported by the SPI controller (otherwise it
would have failed to read the JEDEC ID with the 0xaf op code).
When the QPI mode is disabled, Macronix memories still support the
following Fast Read commands:
- 1-1-1 (0x0b)
- Dual Output 1-1-2 (0x3b)
- Quad Output 1-1-4 (0x6b)
So if the QPI mode has not already been enabled, there is not need to
enable it. We also avoid the 0xbb (Dual I/O 1-2-2) and 0xeb (Quad I/O
1-4-4) op codes on purpose as we don't want to care about the value to set
in mode cycles not to enter the Continuous Read (Performance Enhance)
mode.

As for Micron memories, the spi-nor framework now safely sets the number
of dummy cycles to 8 thanks to 2 volatile bits inside the Configuration
Register.

3 - Spansion:
As for Macronix, we avoid the 0xbb (Dual I/O 1-2-2) and 0xeb (Quad I/O
1-4-4) op codes on purpose as we don't want to care about the value to set
in mode cycles not to enter in the Continuous Read mode.

Besides, we only care about the Quad Enable bit inside the Configuration
Register (CR) when using Quad operations. In such a case, we first check
its state before trying to set it. Now we also notify the user about the
update of this non-volatile bit.

We also check the Latency Code (LC) in CR to know the exact number of
dummy cycles to use when performing a Fast Read operation. Currently only
the 0x0b, 0x3b and 0x6b op codes are used to perform Fast Read operation
so the number of dummy cycles is always either 0 or 8. Hence no regression
should be introduced.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 759 --
 include/linux/mtd/spi-nor.h   |  15 +-
 2 files changed, 675 insertions(+), 99 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index b857e9be2026..4fce01ea16c5 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -126,24 +126,6 @@ static int read_cr(struct spi_nor *nor)
 }
 
 /*
- * Dummy Cycle calculation for different type of read.
- * It can be used to support more commands with
- * different dummy cycle requirements.
- */
-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
-{
-   switch (nor->flash_read) {
-   case SPI_NOR_FAST:
-   case SPI_NOR_DUAL:
-   case SPI_NOR_QUAD:
-  

[PATCH linux-next 4/4] mtd: m25p80: add support of dual and quad spi protocols to all commands

2015-09-18 Thread Cyrille Pitchen
Before this patch, m25p80_read() supported few SPI protocols:
- regular SPI 1-1-1
- SPI Dual Output 1-1-2
- SPI Quad Output 1-1-4
On the other hand, all other m25p80_*() hooks only supported SPI 1-1-1.

However once their Quad mode enabled, Micron and Macronix spi-nor memories
expect all commands to use the SPI 4-4-4 protocol.

Also, once their Dual mode enabled, Micron spi-nor memories expect all
commands to use the SPI-2-2-2 protocol.

So this patch adds support to all currently existing SPI protocols to
cover as many protocols as possible.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/devices/m25p80.c | 254 ---
 1 file changed, 212 insertions(+), 42 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 4b5d7a4655fd..e43caf77732a 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -27,22 +27,110 @@
 #include 
 #include 
 
-#defineMAX_CMD_SIZE6
+#defineMAX_CMD_SIZE8
 struct m25p {
struct spi_device   *spi;
struct spi_nor  spi_nor;
u8  command[MAX_CMD_SIZE];
 };
 
+static inline int m25p80_proto2nbits(enum spi_protocol proto,
+unsigned *code_nbits,
+unsigned *addr_nbits,
+unsigned *data_nbits)
+{
+   unsigned code, addr, data;
+
+   switch (proto) {
+   case SPI_PROTO_1_1_1:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_SINGLE;
+   data = SPI_NBITS_SINGLE;
+   break;
+
+   case SPI_PROTO_1_1_2:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_SINGLE;
+   data = SPI_NBITS_DUAL;
+   break;
+
+   case SPI_PROTO_1_1_4:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_SINGLE;
+   data = SPI_NBITS_QUAD;
+   break;
+
+   case SPI_PROTO_1_2_2:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_DUAL;
+   data = SPI_NBITS_DUAL;
+   break;
+
+   case SPI_PROTO_1_4_4:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_QUAD;
+   data = SPI_NBITS_QUAD;
+   break;
+
+   case SPI_PROTO_2_2_2:
+   code = SPI_NBITS_DUAL;
+   addr = SPI_NBITS_DUAL;
+   data = SPI_NBITS_DUAL;
+   break;
+
+   case SPI_PROTO_4_4_4:
+   code = SPI_NBITS_QUAD;
+   addr = SPI_NBITS_QUAD;
+   data = SPI_NBITS_QUAD;
+   break;
+
+   default:
+   return -EINVAL;
+
+   }
+
+   if (code_nbits)
+   *code_nbits = code;
+   if (addr_nbits)
+   *addr_nbits = addr;
+   if (data_nbits)
+   *data_nbits = data;
+
+   return 0;
+}
+
 static int m25p80_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len)
 {
struct m25p *flash = nor->priv;
struct spi_device *spi = flash->spi;
+   unsigned code_nbits, data_nbits;
+   struct spi_transfer xfers[2];
int ret;
 
-   ret = spi_write_then_read(spi, , 1, val, len);
+   /* Get transfer protocols (addr_nbits is not relevant here). */
+   ret = m25p80_proto2nbits(nor->reg_proto,
+_nbits, NULL, _nbits);
+   if (ret < 0)
+   return ret;
+
+   /* Set up transfers. */
+   memset(xfers, 0, sizeof(xfers));
+
+   flash->command[0] = code;
+   xfers[0].len = 1;
+   xfers[0].tx_buf = flash->command;
+   xfers[0].tx_nbits = code_nbits;
+
+   xfers[1].len = len;
+   xfers[1].rx_buf = >command[1];
+   xfers[1].rx_nbits = data_nbits;
+
+   /* Process command. */
+   ret = spi_sync_transfer(spi, xfers, 2);
if (ret < 0)
dev_err(>dev, "error %d reading %x\n", ret, code);
+   else
+   memcpy(val, >command[1], len);
 
return ret;
 }
@@ -65,12 +153,38 @@ static int m25p80_write_reg(struct spi_nor *nor, u8 
opcode, u8 *buf, int len)
 {
struct m25p *flash = nor->priv;
struct spi_device *spi = flash->spi;
+   unsigned code_nbits, data_nbits, num_xfers = 1;
+   struct spi_transfer xfers[2];
+   int ret;
+
+   /* Get transfer protocols (addr_nbits is not relevant here). */
+   ret = m25p80_proto2nbits(nor->reg_proto,
+_nbits, NULL, _nbits);
+   if (ret < 0)
+   return ret;
+
+   /* Set up transfer(s). */
+   memset(xfers, 0, sizeof(xfers));
 
flash->command[0] = opcode;
-   if (buf)
+   xfers[0].len = 1;
+   xfers[0].tx_buf = flash->command;
+   xfers[0].tx_nbits = code_nbits;
+
+   if (buf) {
 

[PATCH linux-next 0/4] mtd: spi-nor: fix Quad SPI memory support

2015-09-18 Thread Cyrille Pitchen
Hi all,

this series of patches fixes the QSPI support mostly for Micron and
Macronix memories. There are also some updates for Spansion memories.
There are also many comments to explain the implementation choices based
on the datasheets from memory manufacturers.

The series was backported to a at91-4.1 kernel then tested on a sama5d2
xplained board, which embeds a at25df321a memory on a SPI controller and
a Micron n25q128a13 QSPI memory on the new Atmel QSPI controller.

The at25 memory was used to check non regression on the m25p80 driver
whereas the Micron memory was used to test the fixes of the spi-nor
framework. The driver for the Atmel QSPI controller will be sent in a
dedicated series.

Best Regards,

Cyrille

Cyrille Pitchen (4):
  mtd: spi-nor: remove unused read_xfer/write_xfer hooks
  mtd: spi-nor: properly detect the memory when it boots in Quad or Dual
mode
  mtd: spi-nor: fix Quad SPI mode support for Spansion, Micron and
Macronix
  mtd: m25p80: add support of dual and quad spi protocols to all
commands

 drivers/mtd/devices/m25p80.c  | 254 ++---
 drivers/mtd/spi-nor/spi-nor.c | 811 --
 include/linux/mtd/spi-nor.h   |  69 ++--
 3 files changed, 954 insertions(+), 180 deletions(-)

-- 
1.8.2.2

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


[PATCH linux-next 1/4] mtd: spi-nor: remove unused read_xfer/write_xfer hooks

2015-09-18 Thread Cyrille Pitchen
struct spi_nor_xfer_cfg and read_xfer/write_xfer hooks were never used by
any driver. Do some cleanup by removing them.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 include/linux/mtd/spi-nor.h | 35 ---
 1 file changed, 35 deletions(-)

diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index e9c912d73141..672595a381c5 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -87,33 +87,6 @@ enum read_mode {
SPI_NOR_QUAD,
 };
 
-/**
- * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer
- * @wren:  command for "Write Enable", or 0x00 for not required
- * @cmd:   command for operation
- * @cmd_pins:  number of pins to send @cmd (1, 2, 4)
- * @addr:  address for operation
- * @addr_pins: number of pins to send @addr (1, 2, 4)
- * @addr_width:number of address bytes
- * (3,4, or 0 for address not required)
- * @mode:  mode data
- * @mode_pins: number of pins to send @mode (1, 2, 4)
- * @mode_cycles:   number of mode cycles (0 for mode not required)
- * @dummy_cycles:  number of dummy cycles (0 for dummy not required)
- */
-struct spi_nor_xfer_cfg {
-   u8  wren;
-   u8  cmd;
-   u8  cmd_pins;
-   u32 addr;
-   u8  addr_pins;
-   u8  addr_width;
-   u8  mode;
-   u8  mode_pins;
-   u8  mode_cycles;
-   u8  dummy_cycles;
-};
-
 #define SPI_NOR_MAX_CMD_SIZE   8
 enum spi_nor_ops {
SPI_NOR_OPS_READ = 0,
@@ -144,14 +117,11 @@ struct mtd_info;
  * @flash_read:the mode of the read
  * @sst_write_second:  used by the SST write operation
  * @flags: flag options for the current SPI-NOR (SNOR_F_*)
- * @cfg:   used by the read_xfer/write_xfer
  * @cmd_buf:   used by the write_reg
  * @prepare:   [OPTIONAL] do some preparations for the
  * read/write/erase/lock/unlock operations
  * @unprepare: [OPTIONAL] do some post work after the
  * read/write/erase/lock/unlock operations
- * @read_xfer: [OPTIONAL] the read fundamental primitive
- * @write_xfer:[OPTIONAL] the writefundamental primitive
  * @read_reg:  [DRIVER-SPECIFIC] read out the register
  * @write_reg: [DRIVER-SPECIFIC] write data to the register
  * @read:  [DRIVER-SPECIFIC] read data from the SPI NOR
@@ -176,15 +146,10 @@ struct spi_nor {
enum read_mode  flash_read;
boolsst_write_second;
u32 flags;
-   struct spi_nor_xfer_cfg cfg;
u8  cmd_buf[SPI_NOR_MAX_CMD_SIZE];
 
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
-   int (*read_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg,
-u8 *buf, size_t len);
-   int (*write_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg,
- u8 *buf, size_t len);
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
 
-- 
1.8.2.2

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


Re: [linux-next RFC v7 2/6] mtd: spi-nor: read JEDEC ID with multiple I/O protocols

2015-09-16 Thread Cyrille Pitchen
Hi Jagan,

Le 15/09/2015 19:53, Jagan Teki a écrit :
> On 15 September 2015 at 20:58, Cyrille Pitchen
> <cyrille.pitc...@atmel.com> wrote:
>> When their quad or dual I/O mode is enabled, Micron and Macronix spi-nor
>> memories don't reply to the regular Read ID (0x9f) command. Instead they
>> reply to a new dedicated command Read ID Multiple I/O (0xaf).
>>
>> If the Read ID (0x9f) command fails (the read ID is all 1's or all 0's),
>> then the Read ID Multiple I/O (0xaf) is used, first with SPI 4-4-4 protocol
>> (supported by both Micron and Macronix memories), lately with SPI-2-2-2
>> protocol (supported only by Micron memories).
>>
>> Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
>> ---
>>  drivers/mtd/devices/m25p80.c  |  8 +-
>>  drivers/mtd/spi-nor/fsl-quadspi.c |  2 +-
>>  drivers/mtd/spi-nor/nxp-spifi.c   | 13 +++--
>>  drivers/mtd/spi-nor/spi-nor.c | 59 
>> ++-
>>  include/linux/mtd/spi-nor.h   | 27 +++---
>>  5 files changed, 81 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
>> index 4b5d7a4655fd..1457866a4930 100644
>> --- a/drivers/mtd/devices/m25p80.c
>> +++ b/drivers/mtd/devices/m25p80.c
>> @@ -179,7 +179,6 @@ static int m25p_probe(struct spi_device *spi)
>> struct flash_platform_data  *data;
>> struct m25p *flash;
>> struct spi_nor *nor;
>> -   enum read_mode mode = SPI_NOR_NORMAL;
>> char *flash_name = NULL;
>> int ret;
>>
>> @@ -205,11 +204,6 @@ static int m25p_probe(struct spi_device *spi)
>> spi_set_drvdata(spi, flash);
>> flash->spi = spi;
>>
>> -   if (spi->mode & SPI_RX_QUAD)
>> -   mode = SPI_NOR_QUAD;
>> -   else if (spi->mode & SPI_RX_DUAL)
>> -   mode = SPI_NOR_DUAL;
>> -
>> if (data && data->name)
>> nor->mtd.name = data->name;
>>
>> @@ -223,7 +217,7 @@ static int m25p_probe(struct spi_device *spi)
>> else
>> flash_name = spi->modalias;
>>
>> -   ret = spi_nor_scan(nor, flash_name, mode);
>> +   ret = spi_nor_scan(nor, flash_name, spi->mode);
> 
> IMHO, this is certainly incorrect because spi-nor never know anything
> about spi (Linux) that is why this framework got into picture.
> 

OK but what to use instead? Because we need to know the SPI controller
capabilities as compared to what the SPI NOR memory expects.

SPI_NOR_QUAD is just not enough as it doesn't allow us to make the difference
between SPI 1-1-4, 1-4-4 or 4-4-4 protocols.
Some manufacturer specific commands like Multiple I/O Read ID (0xaf) only work
with the SPI 4-4-4 protocol.

Also patch 3 (mtd: spi-nor: set the read op code and protocol based on the
manufacturer) makes use of the SPI controller capabilities to select the right
Fast Read op code and SPI protocol to match the SPI NOR memory interface.

Currently the framework always uses the Fast Read Quad Output 1-1-4 (0x6b).
Then for Macronix QSPI memories, the framework also enables their QPI mode.
However the datasheet of Macronix MX66L1G claims this command (0x6b) is only
supported in in SPI mode but not in QPI mode.

Also for Micron QSPI memories, the framework turns their Quad mode on but once
enabled the spi-nor memories expected ALL commands to use the SPI 4-4-4
protocol. SPI controllers have no mean to be notified about that protocol
change.

Besides, the m25p80 driver only checks the SPI_RX_QUAD flag before asking the
spi-nor framework to use some Quad SPI mode but in many cases it's not enough;
the SPI_TX_QUAD flag is also needed.

Of course there are other ways to provide the spi-nor framework with the SPI
controller. Maybe we can still use a bitmask for its simplicity of use by
changing a little bit the definition of the spi_protocol constants:

#define SPI_PROTO_1_1_10x0001
#define SPI_PROTO_1_1_20x0002
#define SPI_PROTO_1_1_40x0004
#define SPI_PROTO_1_2_20x0008
#define SPI_PROTO_1_4_40x0010
#define SPI_PROTO_2_2_20x0020
#define SPI_PROTO_4_4_40x0040

Then for instance in m25p80.c, we do something like:

unsigned int supported_protocols = SPI_PROTO_1_1_1;

if (spi->mode & SPI_RX_QUAD) {
supported_protocols |= SPI_PROTO_1_1_4;

if (spi->mode & SPI_TX_QUAD)
supported_protocols |= (SPI_PROTO_1_4_4 | SPI_PROTO_4_4_4);
}

if (spi->mode & SPI_RX_DUAL) {
supported_protocols |= SPI_PROTO_1_1_2;

if (spi->mode & SPI_TX_DUAL)
supported_protocols |= (SPI_PROTO_1_2_2 | SPI_PROTO_2_2_2);
}


[linux-next RFC v7 5/6] Documentation: atmel-quadspi: add binding file for Atmel QSPI driver

2015-09-15 Thread Cyrille Pitchen
This patch documents the DT bindings for the driver of the Atmel QSPI
controller embedded inside sama5d2x SoCs.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
Acked-by: Nicolas Ferre <nicolas.fe...@atmel.com>
Acked-by: Marek Vasut <ma...@denx.de>
Acked-by: Rob Herring <r...@kernel.org>
---
 .../devicetree/bindings/mtd/atmel-quadspi.txt  | 29 ++
 1 file changed, 29 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt

diff --git a/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt 
b/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
new file mode 100644
index ..0b8d545bb198
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
@@ -0,0 +1,29 @@
+* Atmel Quad Serial Peripheral Interface (QSPI)
+
+Required properties:
+- compatible: should be "atmel,sama5d2-qspi"
+- reg:the first contains the register location and length,
+  the second contains the memory mapping address and length
+- interrupts: should contain the interrupt for the device
+- clocks: the phandle of the clock needed by the QSPI controller
+- #address-cells: should be <1>
+- #size-cells:should be <0>
+
+Example:
+
+spi@f002 {
+   compatible = "atmel,sama5d2-qspi";
+   reg = <0xf002 0x100>,
+ <0xd000 0x800>;
+   interrupts = <52 IRQ_TYPE_LEVEL_HIGH 7>;
+   clocks = <_clk>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   pinctrl-names = "default";
+   pinctrl-0 = <_spi0_default>;
+   status = "okay";
+
+   m25p80@0 {
+   ...
+   };
+};
-- 
1.8.2.2

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


[linux-next RFC v7 0/6] mtd: spi-nor: improve support of QSPI nor

2015-09-15 Thread Cyrille Pitchen
Hi all,

this series is still a work in progress though it is almost finished.
The support of Macronix dummy code to configure the number of dummy cycles
is still missing...

However I would like some feedbacks to synchronize this work with other
mtd / spi-nor improvements as I see lots of patches on the mailing list.

Best Regards,

Cyrille

Cyrille Pitchen (6):
  mtd: spi-nor: remove unused read_xfer/write_xfer hooks
  mtd: spi-nor: read JEDEC ID with multiple I/O protocols
  mtd: spi-nor: set the read op code and protocol based on the
manufacturer
  mtd: m25p80: add support of dual and quad spi protocols to all
commands
  Documentation: atmel-quadspi: add binding file for Atmel QSPI driver
  mtd: atmel-quadspi: add driver for Atmel QSPI controller

 .../devicetree/bindings/mtd/atmel-quadspi.txt  |  29 +
 drivers/mtd/devices/m25p80.c   | 262 --
 drivers/mtd/spi-nor/Kconfig|   7 +
 drivers/mtd/spi-nor/Makefile   |   1 +
 drivers/mtd/spi-nor/atmel-quadspi.c| 880 +
 drivers/mtd/spi-nor/fsl-quadspi.c  |   2 +-
 drivers/mtd/spi-nor/nxp-spifi.c|  13 +-
 drivers/mtd/spi-nor/spi-nor.c  | 603 --
 include/linux/mtd/spi-nor.h|  68 +-
 9 files changed, 1689 insertions(+), 176 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

-- 
1.8.2.2

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


[linux-next RFC v7 3/6] mtd: spi-nor: set the read op code and protocol based on the manufacturer

2015-09-15 Thread Cyrille Pitchen
Micron:
Once their Quad SPI protocol enabled, Micron spi-nor memories expect all
commands to use the SPI 4-4-4 protocol. Also when the Dual SPI protocol is
enabled, all commands must use the SPI 2-2-2 protocol.

Macronix:
When the QPI mode is enabled, all commands must use the SPI 4-4-4 protocol.
If the QPI mode is disabled, the Fast Read Dual Output (0x3b) command uses
the SPI 1-1-2 protocol whereas other commands use the SPI 1-1-1 protocol.

Spansion:
When Quad I/O operations are enabled, the Fast Read Quad Output (0x6b / 0x6c)
commands use the SPI 1-1-4 protocol.
Also when using the Fast Read Dual Output (0x3b / 0x3c) commands, the
SPI 1-1-2 protocol must be used. Other commands use the SPI 1-1-1 protocol.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 544 --
 include/linux/mtd/spi-nor.h   |  10 +-
 2 files changed, 481 insertions(+), 73 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 1908038c8f2e..7fbcccb3d02e 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -900,27 +900,110 @@ write_err:
return ret;
 }
 
-static int macronix_quad_enable(struct spi_nor *nor)
+static int macronix_set_qpi_mode(struct spi_nor *nor, bool enable)
 {
-   int ret, val;
+   int sr, mask, qpi_bit;
+
+   mask = SR_QUAD_EN_MX;
+   qpi_bit = (enable) ? SR_QUAD_EN_MX : 0;
+
+   sr = read_sr(nor);
+   if ((sr & mask) == qpi_bit)
+   return 0;
 
-   val = read_sr(nor);
write_enable(nor);
+   write_sr(nor, (sr & ~mask) | qpi_bit);
 
-   write_sr(nor, val | SR_QUAD_EN_MX);
+   /* Set the reg protocol now before accessing any other register. */
+   nor->reg_proto = (enable) ? SPI_PROTO_4_4_4 : SPI_PROTO_1_1_1;
 
-   if (spi_nor_wait_till_ready(nor))
+   if (spi_nor_wait_till_ready(nor)) {
+   dev_err(nor->dev, "Failed to %s the QPI mode.\n",
+   enable ? "enable" : "disable");
return 1;
+   }
 
-   ret = read_sr(nor);
-   if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) {
-   dev_err(nor->dev, "Macronix Quad bit not set\n");
+   sr = read_sr(nor);
+   if (!(sr > 0 && ((sr & mask) != qpi_bit))) {
+   dev_err(nor->dev, "Macronix Quad bit was not %s.\n",
+   enable ? "set" : "cleared");
return -EINVAL;
}
 
return 0;
 }
 
+static int macronix_set_quad_io(struct spi_nor *nor)
+{
+   /* Enable the QPI mode if not done yet. */
+   if (macronix_set_qpi_mode(nor, true))
+   return -EINVAL;
+
+   /* Use SPI 4-4-4 protocol for all commands. */
+   nor->read_proto = SPI_PROTO_4_4_4;
+   nor->write_proto = SPI_PROTO_4_4_4;
+   nor->erase_proto = SPI_PROTO_4_4_4;
+
+   /*
+* The Fast Read Quad Output 1-1-4 command (0x6b) command is not
+* supported in QPI mode, use the Fast Read Quad I/O 1-4-4 (0xeb)
+* instead.
+*/
+   nor->read_opcode = SPINOR_OP_READ_1_4_4;
+
+   return 0;
+}
+
+static int macronix_set_quad_output(struct spi_nor *nor)
+{
+   /* Disable the QPI mode if not done yet. */
+   if (macronix_set_qpi_mode(nor, false))
+   return -EINVAL;
+
+   /* Use the Fast Read Quad Output 1-1-4 command. */
+   nor->read_proto = SPI_PROTO_1_1_4;
+   nor->read_opcode = SPINOR_OP_READ_1_1_4;
+
+   return 0;
+}
+
+static int macronix_set_dual_io(struct spi_nor *nor)
+{
+   /* Disable the QPI mode if not done yet. */
+   if (macronix_set_qpi_mode(nor, false))
+   return -EINVAL;
+
+   /* Use the Fast Read Dual I/O 1-2-2 command. */
+   nor->read_proto = SPI_PROTO_1_2_2;
+   nor->read_opcode = SPINOR_OP_READ_1_2_2;
+
+   return 0;
+}
+
+static int macronix_set_dual_output(struct spi_nor *nor)
+{
+   /* Disable the QPI mode if not done yet. */
+   if (macronix_set_qpi_mode(nor, false))
+   return -EINVAL;
+
+   /* Use the Fast Read Dual Output 1-1-2 command. */
+   nor->read_proto = SPI_PROTO_1_1_2;
+   nor->read_opcode = SPINOR_OP_READ_1_1_2;
+
+   return 0;
+}
+
+static int macronix_set_single(struct spi_nor *nor)
+{
+   /* Disable the QPI mode if not done yet. */
+   if (macronix_set_qpi_mode(nor, false))
+   return -EINVAL;
+
+   nor->read_proto = SPI_PROTO_1_1_1;
+
+   return 0;
+}
+
 /*
  * Write status Register and configuration register with 2 bytes
  * The first byte will be written to the status register, while the
@@ -935,96 +1018,416 @@ static int write_sr_cr(struct spi_nor *nor, u16 val)
return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2);
 }
 
-static int spansion_quad

[linux-next RFC v7 1/6] mtd: spi-nor: remove unused read_xfer/write_xfer hooks

2015-09-15 Thread Cyrille Pitchen
struct spi_nor_xfer_cfg and read_xfer/write_xfer hooks were never used by
any driver. Do some cleanup by removing them.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 include/linux/mtd/spi-nor.h | 35 ---
 1 file changed, 35 deletions(-)

diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index e9c912d73141..672595a381c5 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -87,33 +87,6 @@ enum read_mode {
SPI_NOR_QUAD,
 };
 
-/**
- * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer
- * @wren:  command for "Write Enable", or 0x00 for not required
- * @cmd:   command for operation
- * @cmd_pins:  number of pins to send @cmd (1, 2, 4)
- * @addr:  address for operation
- * @addr_pins: number of pins to send @addr (1, 2, 4)
- * @addr_width:number of address bytes
- * (3,4, or 0 for address not required)
- * @mode:  mode data
- * @mode_pins: number of pins to send @mode (1, 2, 4)
- * @mode_cycles:   number of mode cycles (0 for mode not required)
- * @dummy_cycles:  number of dummy cycles (0 for dummy not required)
- */
-struct spi_nor_xfer_cfg {
-   u8  wren;
-   u8  cmd;
-   u8  cmd_pins;
-   u32 addr;
-   u8  addr_pins;
-   u8  addr_width;
-   u8  mode;
-   u8  mode_pins;
-   u8  mode_cycles;
-   u8  dummy_cycles;
-};
-
 #define SPI_NOR_MAX_CMD_SIZE   8
 enum spi_nor_ops {
SPI_NOR_OPS_READ = 0,
@@ -144,14 +117,11 @@ struct mtd_info;
  * @flash_read:the mode of the read
  * @sst_write_second:  used by the SST write operation
  * @flags: flag options for the current SPI-NOR (SNOR_F_*)
- * @cfg:   used by the read_xfer/write_xfer
  * @cmd_buf:   used by the write_reg
  * @prepare:   [OPTIONAL] do some preparations for the
  * read/write/erase/lock/unlock operations
  * @unprepare: [OPTIONAL] do some post work after the
  * read/write/erase/lock/unlock operations
- * @read_xfer: [OPTIONAL] the read fundamental primitive
- * @write_xfer:[OPTIONAL] the writefundamental primitive
  * @read_reg:  [DRIVER-SPECIFIC] read out the register
  * @write_reg: [DRIVER-SPECIFIC] write data to the register
  * @read:  [DRIVER-SPECIFIC] read data from the SPI NOR
@@ -176,15 +146,10 @@ struct spi_nor {
enum read_mode  flash_read;
boolsst_write_second;
u32 flags;
-   struct spi_nor_xfer_cfg cfg;
u8  cmd_buf[SPI_NOR_MAX_CMD_SIZE];
 
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
-   int (*read_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg,
-u8 *buf, size_t len);
-   int (*write_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg,
- u8 *buf, size_t len);
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
 
-- 
1.8.2.2

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


[linux-next RFC v7 6/6] mtd: atmel-quadspi: add driver for Atmel QSPI controller

2015-09-15 Thread Cyrille Pitchen
This driver add support to the new Atmel QSPI controller embedded into
sama5d2x SoCs. It expects a NOR memory to be connected to the QSPI
controller.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi-nor/Kconfig |   7 +
 drivers/mtd/spi-nor/Makefile|   1 +
 drivers/mtd/spi-nor/atmel-quadspi.c | 880 
 3 files changed, 888 insertions(+)
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 89bf4c1faa2b..7a3d55429550 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -29,6 +29,13 @@ config SPI_FSL_QUADSPI
  This controller does not support generic SPI. It only supports
  SPI NOR.
 
+config SPI_ATMEL_QUADSPI
+   tristate "Atmel Quad SPI Controller"
+   depends on OF && HAS_DMA && (ARCH_AT91 || COMPILE_TEST)
+   help
+ This enables support for the Quad SPI controller in master mode.
+ We only connect the NOR to this controller now.
+
 config SPI_NXP_SPIFI
tristate "NXP SPI Flash Interface (SPIFI)"
depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index e5ef8582..f5d23d7379bb 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_MTD_SPI_NOR)  += spi-nor.o
 obj-$(CONFIG_SPI_FSL_QUADSPI)  += fsl-quadspi.o
+obj-$(CONFIG_SPI_ATMEL_QUADSPI)+= atmel-quadspi.o
 obj-$(CONFIG_SPI_NXP_SPIFI)+= nxp-spifi.o
diff --git a/drivers/mtd/spi-nor/atmel-quadspi.c 
b/drivers/mtd/spi-nor/atmel-quadspi.c
new file mode 100644
index ..e938152c2c89
--- /dev/null
+++ b/drivers/mtd/spi-nor/atmel-quadspi.c
@@ -0,0 +1,880 @@
+/*
+ * Driver for Atmel QSPI Controller
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen <cyrille.pitc...@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This driver is based on drivers/mtd/spi-nor/fsl-quadspi.c from Freescale.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+/* QSPI register offsets */
+#define QSPI_CR  0x  /* Control Register */
+#define QSPI_MR  0x0004  /* Mode Register */
+#define QSPI_RD  0x0008  /* Receive Data Register */
+#define QSPI_TD  0x000c  /* Transmit Data Register */
+#define QSPI_SR  0x0010  /* Status Register */
+#define QSPI_IER 0x0014  /* Interrupt Enable Register */
+#define QSPI_IDR 0x0018  /* Interrupt Disable Register */
+#define QSPI_IMR 0x001c  /* Interrupt Mask Register */
+#define QSPI_SCR 0x0020  /* Serial Clock Register */
+
+#define QSPI_IAR 0x0030  /* Instruction Address Register */
+#define QSPI_ICR 0x0034  /* Instruction Code Register */
+#define QSPI_IFR 0x0038  /* Instruction Frame Register */
+
+#define QSPI_SMR 0x0040  /* Scrambling Mode Register */
+#define QSPI_SKR 0x0044  /* Scrambling Key Register */
+
+#define QSPI_WPMR0x00E4  /* Write Protection Mode Register */
+#define QSPI_WPSR0x00E8  /* Write Protection Status Register */
+
+#define QSPI_VERSION 0x00FC  /* Version Register */
+
+
+/* Bitfields in QSPI_CR (Control Register) */
+#define QSPI_CR_QSPIEN  BIT(0)
+#define QSPI_CR_QSPIDIS BIT(1)
+#define QSPI_CR_SWRST   BIT(7)
+#define QSPI_CR_LASTXFERBIT(24)
+
+/* Bitfields in QSPI_MR (Mode Register) */
+#define QSPI_MR_SSM BIT(0)
+#define QSPI_MR_LLB BIT(1)
+#define QSPI_MR_WDRBT   BIT(2)
+#define QSPI_MR_SMRMBIT(3)
+#define QSPI_MR_CSMODE_MASK GENMASK(5, 4)
+#define QSPI_MR_CSMODE_NOT_RELOADED (0 << 4)
+#define QSPI_MR_CSMODE_LASTXFER (1 << 4)
+#define QSPI_MR_CSMODE_SYSTEMATICALLY   (2 << 4)
+#define QSPI_MR_NBBITS_MASK GENMASK(11, 8)
+#define QSPI_MR_NBBITS(n)   n) - 8) << 8) & 
QSPI_MR_NBBITS_MASK)
+#define QSPI_MR_DLYBCT_MASK GENMASK(23, 16)
+#define QSPI_MR_DLYBCT(n)   (((n) << 16) & QSPI_MR_DLYBCT_MASK)
+#define QSPI_MR_DLYCS_MASK

[linux-next RFC v7 4/6] mtd: m25p80: add support of dual and quad spi protocols to all commands

2015-09-15 Thread Cyrille Pitchen
Before this patch, m25p80_read() supported few SPI protocols:
- regular SPI 1-1-1
- SPI Dual Output 1-1-2
- SPI Quad Output 1-1-4
On the other hand, all other m25p80_*() hooks only supported SPI 1-1-1.

However once their Quad mode enabled, Micron and Macronix spi-nor memories
expect all commands to use the SPI 4-4-4 protocol.

Also, once their Dual mode enabled, Micron spi-nor memories expect all
commands to use the SPI-2-2-2 protocol.

So this patch adds support to all currently existing SPI protocols to
cover as many protocols as possible.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/devices/m25p80.c | 254 ---
 1 file changed, 212 insertions(+), 42 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 1457866a4930..96072b33b29f 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -27,22 +27,110 @@
 #include 
 #include 
 
-#defineMAX_CMD_SIZE6
+#defineMAX_CMD_SIZE8
 struct m25p {
struct spi_device   *spi;
struct spi_nor  spi_nor;
u8  command[MAX_CMD_SIZE];
 };
 
+static inline int m25p80_proto2nbits(enum spi_protocol proto,
+unsigned *code_nbits,
+unsigned *addr_nbits,
+unsigned *data_nbits)
+{
+   unsigned code, addr, data;
+
+   switch (proto) {
+   case SPI_PROTO_1_1_1:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_SINGLE;
+   data = SPI_NBITS_SINGLE;
+   break;
+
+   case SPI_PROTO_1_1_2:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_SINGLE;
+   data = SPI_NBITS_DUAL;
+   break;
+
+   case SPI_PROTO_1_1_4:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_SINGLE;
+   data = SPI_NBITS_QUAD;
+   break;
+
+   case SPI_PROTO_1_2_2:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_DUAL;
+   data = SPI_NBITS_DUAL;
+   break;
+
+   case SPI_PROTO_1_4_4:
+   code = SPI_NBITS_SINGLE;
+   addr = SPI_NBITS_QUAD;
+   data = SPI_NBITS_QUAD;
+   break;
+
+   case SPI_PROTO_2_2_2:
+   code = SPI_NBITS_DUAL;
+   addr = SPI_NBITS_DUAL;
+   data = SPI_NBITS_DUAL;
+   break;
+
+   case SPI_PROTO_4_4_4:
+   code = SPI_NBITS_QUAD;
+   addr = SPI_NBITS_QUAD;
+   data = SPI_NBITS_QUAD;
+   break;
+
+   default:
+   return -EINVAL;
+
+   }
+
+   if (code_nbits)
+   *code_nbits = code;
+   if (addr_nbits)
+   *addr_nbits = addr;
+   if (data_nbits)
+   *data_nbits = data;
+
+   return 0;
+}
+
 static int m25p80_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len)
 {
struct m25p *flash = nor->priv;
struct spi_device *spi = flash->spi;
+   unsigned code_nbits, data_nbits;
+   struct spi_transfer xfers[2];
int ret;
 
-   ret = spi_write_then_read(spi, , 1, val, len);
+   /* Get transfer protocols (addr_nbits is not relevant here). */
+   ret = m25p80_proto2nbits(nor->reg_proto,
+_nbits, NULL, _nbits);
+   if (ret < 0)
+   return ret;
+
+   /* Set up transfers. */
+   memset(xfers, 0, sizeof(xfers));
+
+   flash->command[0] = code;
+   xfers[0].len = 1;
+   xfers[0].tx_buf = flash->command;
+   xfers[0].tx_nbits = code_nbits;
+
+   xfers[1].len = len;
+   xfers[1].rx_buf = >command[1];
+   xfers[1].rx_nbits = data_nbits;
+
+   /* Process command. */
+   ret = spi_sync_transfer(spi, xfers, 2);
if (ret < 0)
dev_err(>dev, "error %d reading %x\n", ret, code);
+   else
+   memcpy(val, >command[1], len);
 
return ret;
 }
@@ -65,12 +153,38 @@ static int m25p80_write_reg(struct spi_nor *nor, u8 
opcode, u8 *buf, int len)
 {
struct m25p *flash = nor->priv;
struct spi_device *spi = flash->spi;
+   unsigned code_nbits, data_nbits, num_xfers = 1;
+   struct spi_transfer xfers[2];
+   int ret;
+
+   /* Get transfer protocols (addr_nbits is not relevant here). */
+   ret = m25p80_proto2nbits(nor->reg_proto,
+_nbits, NULL, _nbits);
+   if (ret < 0)
+   return ret;
+
+   /* Set up transfer(s). */
+   memset(xfers, 0, sizeof(xfers));
 
flash->command[0] = opcode;
-   if (buf)
+   xfers[0].len = 1;
+   xfers[0].tx_buf = flash->command;
+   xfers[0].tx_nbits = code_nbits;
+
+   if (buf) {
 

[linux-next RFC v7 2/6] mtd: spi-nor: read JEDEC ID with multiple I/O protocols

2015-09-15 Thread Cyrille Pitchen
When their quad or dual I/O mode is enabled, Micron and Macronix spi-nor
memories don't reply to the regular Read ID (0x9f) command. Instead they
reply to a new dedicated command Read ID Multiple I/O (0xaf).

If the Read ID (0x9f) command fails (the read ID is all 1's or all 0's),
then the Read ID Multiple I/O (0xaf) is used, first with SPI 4-4-4 protocol
(supported by both Micron and Macronix memories), lately with SPI-2-2-2
protocol (supported only by Micron memories).

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/devices/m25p80.c  |  8 +-
 drivers/mtd/spi-nor/fsl-quadspi.c |  2 +-
 drivers/mtd/spi-nor/nxp-spifi.c   | 13 +++--
 drivers/mtd/spi-nor/spi-nor.c | 59 ++-
 include/linux/mtd/spi-nor.h   | 27 +++---
 5 files changed, 81 insertions(+), 28 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 4b5d7a4655fd..1457866a4930 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -179,7 +179,6 @@ static int m25p_probe(struct spi_device *spi)
struct flash_platform_data  *data;
struct m25p *flash;
struct spi_nor *nor;
-   enum read_mode mode = SPI_NOR_NORMAL;
char *flash_name = NULL;
int ret;
 
@@ -205,11 +204,6 @@ static int m25p_probe(struct spi_device *spi)
spi_set_drvdata(spi, flash);
flash->spi = spi;
 
-   if (spi->mode & SPI_RX_QUAD)
-   mode = SPI_NOR_QUAD;
-   else if (spi->mode & SPI_RX_DUAL)
-   mode = SPI_NOR_DUAL;
-
if (data && data->name)
nor->mtd.name = data->name;
 
@@ -223,7 +217,7 @@ static int m25p_probe(struct spi_device *spi)
else
flash_name = spi->modalias;
 
-   ret = spi_nor_scan(nor, flash_name, mode);
+   ret = spi_nor_scan(nor, flash_name, spi->mode);
if (ret)
return ret;
 
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c 
b/drivers/mtd/spi-nor/fsl-quadspi.c
index 2954f89fc8be..1ded5dbe2240 100644
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
@@ -1033,7 +1033,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
/* set the chip address for READID */
fsl_qspi_set_base_addr(q, nor);
 
-   ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD);
+   ret = spi_nor_scan(nor, NULL, SPI_RX_QUAD);
if (ret)
goto mutex_failed;
 
diff --git a/drivers/mtd/spi-nor/nxp-spifi.c b/drivers/mtd/spi-nor/nxp-spifi.c
index 9e82098ae644..c499f3258245 100644
--- a/drivers/mtd/spi-nor/nxp-spifi.c
+++ b/drivers/mtd/spi-nor/nxp-spifi.c
@@ -272,7 +272,6 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi,
 struct device_node *np)
 {
struct mtd_part_parser_data ppdata;
-   enum read_mode flash_read;
u32 ctrl, property;
u16 mode = 0;
int ret;
@@ -304,16 +303,12 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi,
   SPIFI_CTRL_CSHIGH(15) |
   SPIFI_CTRL_FBCLK;
 
-   if (mode & SPI_RX_DUAL) {
+   if (mode & SPI_RX_DUAL)
ctrl |= SPIFI_CTRL_DUAL;
-   flash_read = SPI_NOR_DUAL;
-   } else if (mode & SPI_RX_QUAD) {
+   else if (mode & SPI_RX_QUAD)
ctrl &= ~SPIFI_CTRL_DUAL;
-   flash_read = SPI_NOR_QUAD;
-   } else {
+   else
ctrl |= SPIFI_CTRL_DUAL;
-   flash_read = SPI_NOR_NORMAL;
-   }
 
switch (mode & (SPI_CPHA | SPI_CPOL)) {
case SPI_MODE_0:
@@ -349,7 +344,7 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi,
 */
nxp_spifi_dummy_id_read(>nor);
 
-   ret = spi_nor_scan(>nor, NULL, flash_read);
+   ret = spi_nor_scan(>nor, NULL, mode);
if (ret) {
dev_err(spifi->dev, "device scan failed\n");
return ret;
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 8818d4325d20..1908038c8f2e 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -61,6 +62,11 @@ struct flash_info {
 
 #define JEDEC_MFR(info)((info)->id[0])
 
+struct read_id_proto {
+   enum spi_protocol   proto;  /* SPI protocol to read the JEDEC ID */
+   u16 mode;   /* SPI controller required caps */
+};
+
 static const struct flash_info *spi_nor_match_id(const char *name);
 
 /*
@@ -701,11 +707,15 @@ static const struct flash_info spi_nor_ids[] = {
{ },
 };
 
-static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
+static const struct flash_info *spi_nor_read_id(struct spi_nor *nor, u16 m

[PATCH linux-next v6 0/8] add driver for Atmel QSPI controller

2015-09-09 Thread Cyrille Pitchen
ChangeLog

v6:
- add new patch which tries to read the JEDEC ID with different SPI protocols
  and different commands: 0x9f (SPI-1-1-1), 0xaf (SPI-4-4-4) and finally
  0xaf (SPI-2-2-2).
- remove the set_protocol() hook from struct spi_nor and add 4 new members
  instead of type enum spi_protocol:
  read_proto, write_proto, erase_proto, reg_proto.
  The relevant protocol value should be checked by the driver specific read(),
  write(), erase(), read_reg() and write_reg() hook implementations.
- remove unused hooks: write_xfer() and read_xfer().
- tune the op code for read, write and erase commands depending on the memory
  manufacturer.
- remove some previously added "Acked-by" since the protocol switch strategy
  has been changed but not discussed yet.

v5:
- remove unused inline functions qspi_read[bw]() and qspi_write[bw](),
  keep only qspi_readl() and qspi_writel().
- use reinit_completion() instead of init_completion() during run time,
  call init_completion() once for all in the probe().
- add a dev_warn() when trying to tune the number of dummy cycles for
  spi-nor of a not supported manufacturer then fall back to the default
  framework value.
- reword some comments.
- add "Acked-by: Marek Vasut <ma...@denx.de>" for patches 1 and 4.
- add "Acked-by: Bean Huo <bean...@micron.com>" for patch 1.

v4:
- add "OF && HAS_DMA" dependency in Kconfig for Atmel Quad SPI driver.
- return -ENOMEM instead of the return code of dma_mapping_error() as this
  function returns a boolean on ARM achitecture.
- add "Acked-by: Nicolas Ferre <nicolas.fe...@atmel.com>" for Atmel Quad
  SPI driver and its DT binding documentation.

v3:
- reword the comment which explains that spi_nor_set_protocol() is used by
  the spi-nor framework to notify lower layers, especially the (Q)SPI
  controller about a protocol change.
- change the definitions of register/bitfield macros in the Atmel QSPI
  controller driver: get rid of concatenation operator and use BIT and
  GENMASK macros when possible.
- use #define[SPACE] instead of #define[TAB]

v2:
- remove the patches to set the "latency code" of Spansion QSPI memories
  (support of Spansion memories may be submitted in later series).
- rename "qspi" node into "spi" in the DT example to fit ePAPR standard.
- remove the useless "qspi0" label from the DT node example.
- remove the leading 0 from the size of the second memory region to make
  it consistent with the size of the first memory region.
- indent the DT bindings documentation to make it more readable.
- remove the useless ".bus  = _bus_type," line from the
  platform driver definition.

v1:

This series of patches add support for the new Atmel QSPI controller
embedded inside sama5d2x SoCs.

These patches were first developped for linux-3.18-at91 and tested on a
sama5d27 Xplained ultra board, which embeds a Micron n25q128a13 QSPI NOR
flash memory. Then the series was adapted for mainline.

Cyrille Pitchen (8):
  mtd: spi-nor: read JEDEC ID with multiple I/O protocols
  mtd: spi-nor: remove unused read_xfer/write_xfer hooks
  mtd: spi-nor: update the SPI protocol when enabling manufacturer Quad
mode
  mtd: spi-nor: use optimized commands for read/write/erase operations
  Documentation: mtd: add a DT property to set the number of dummy
cycles
  mtd: spi-nor: allow to tune the number of dummy cycles
  Documentation: atmel-quadspi: add binding file for Atmel QSPI driver
  mtd: atmel-quadspi: add driver for Atmel QSPI controller

 .../devicetree/bindings/mtd/atmel-quadspi.txt  |  29 +
 .../devicetree/bindings/mtd/jedec,spi-nor.txt  |   6 +
 drivers/mtd/spi-nor/Kconfig|   7 +
 drivers/mtd/spi-nor/Makefile   |   1 +
 drivers/mtd/spi-nor/atmel-quadspi.c| 889 +
 drivers/mtd/spi-nor/spi-nor.c  | 356 +++--
 include/linux/mtd/spi-nor.h|  63 +-
 7 files changed, 1269 insertions(+), 82 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

-- 
1.8.2.2

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


[PATCH linux-next v6 2/8] mtd: spi-nor: remove unused read_xfer/write_xfer hooks

2015-09-09 Thread Cyrille Pitchen
struct spi_nor_xfer_cfg and read_xfer/write_xfer hooks were never used by
any driver. Do some cleanup by removing them.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 include/linux/mtd/spi-nor.h | 35 ---
 1 file changed, 35 deletions(-)

diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 66a5f144728a..08e405cbb6af 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -98,33 +98,6 @@ enum spi_protocol {
SPI_PROTO_4_4_4,/* Quad Command */
 };
 
-/**
- * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer
- * @wren:  command for "Write Enable", or 0x00 for not required
- * @cmd:   command for operation
- * @cmd_pins:  number of pins to send @cmd (1, 2, 4)
- * @addr:  address for operation
- * @addr_pins: number of pins to send @addr (1, 2, 4)
- * @addr_width:number of address bytes
- * (3,4, or 0 for address not required)
- * @mode:  mode data
- * @mode_pins: number of pins to send @mode (1, 2, 4)
- * @mode_cycles:   number of mode cycles (0 for mode not required)
- * @dummy_cycles:  number of dummy cycles (0 for dummy not required)
- */
-struct spi_nor_xfer_cfg {
-   u8  wren;
-   u8  cmd;
-   u8  cmd_pins;
-   u32 addr;
-   u8  addr_pins;
-   u8  addr_width;
-   u8  mode;
-   u8  mode_pins;
-   u8  mode_cycles;
-   u8  dummy_cycles;
-};
-
 #define SPI_NOR_MAX_CMD_SIZE   8
 enum spi_nor_ops {
SPI_NOR_OPS_READ = 0,
@@ -152,7 +125,6 @@ enum spi_nor_option_flags {
  * @flash_read:the mode of the read
  * @sst_write_second:  used by the SST write operation
  * @flags: flag options for the current SPI-NOR (SNOR_F_*)
- * @cfg:   used by the read_xfer/write_xfer
  * @erase_proto:   the SPI protocol used by erase operations
  * @read_proto:the SPI protocol used by read operations
  * @write_proto:   the SPI protocol used by write operations
@@ -162,8 +134,6 @@ enum spi_nor_option_flags {
  * read/write/erase/lock/unlock operations
  * @unprepare: [OPTIONAL] do some post work after the
  * read/write/erase/lock/unlock operations
- * @read_xfer: [OPTIONAL] the read fundamental primitive
- * @write_xfer:[OPTIONAL] the writefundamental primitive
  * @read_reg:  [DRIVER-SPECIFIC] read out the register
  * @write_reg: [DRIVER-SPECIFIC] write data to the register
  * @read:  [DRIVER-SPECIFIC] read data from the SPI NOR
@@ -191,15 +161,10 @@ struct spi_nor {
enum read_mode  flash_read;
boolsst_write_second;
u32 flags;
-   struct spi_nor_xfer_cfg cfg;
u8  cmd_buf[SPI_NOR_MAX_CMD_SIZE];
 
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
-   int (*read_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg,
-u8 *buf, size_t len);
-   int (*write_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg,
- u8 *buf, size_t len);
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len,
int write_enable);
-- 
1.8.2.2

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


[PATCH linux-next v6 3/8] mtd: spi-nor: update the SPI protocol when enabling manufacturer Quad mode

2015-09-09 Thread Cyrille Pitchen
Micron:
Once their Quad SPI protocol enabled, Micron spi-nor memories expect all
commands to use the SPI 4-4-4 protocol. Also when the Dual SPI protocol is
enabled, all commands must use the SPI 2-2-2 protocol.

Macronix:
When the QPI mode is enabled, all commands must use the SPI 4-4-4 protocol.

Spansion:
When Quad I/O operations are enabled, the Fast Read Quad Output (0x6b / 0x6c)
commands use the SPI 1-1-4 protocol, the Page Program Quad Output (0x32 /
0x34) command use the SPI 1-1-4 protocol whereas other commands use the
SPI 1-1-1 protocol.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 74 ---
 include/linux/mtd/spi-nor.h   |  1 +
 2 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 80a0db078aaa..4b36aada3f4c 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -891,6 +891,12 @@ static int macronix_quad_enable(struct spi_nor *nor)
nor->cmd_buf[0] = val | SR_QUAD_EN_MX;
nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0);
 
+   /* Once QPI mode enabled, all commands use SPI 4-4-4 protocol. */
+   nor->erase_proto = SPI_PROTO_4_4_4;
+   nor->read_proto = SPI_PROTO_4_4_4;
+   nor->write_proto = SPI_PROTO_4_4_4;
+   nor->reg_proto = SPI_PROTO_4_4_4;
+
if (spi_nor_wait_till_ready(nor))
return 1;
 
@@ -938,10 +944,16 @@ static int spansion_quad_enable(struct spi_nor *nor)
return -EINVAL;
}
 
+   /* set read/write protocols */
+   nor->read_proto = SPI_PROTO_1_1_4;
+   nor->write_proto = SPI_PROTO_1_1_4;
+
return 0;
 }
 
-static int micron_quad_enable(struct spi_nor *nor)
+static int micron_set_protocol(struct spi_nor *nor,
+  u8 mask, u8 value,
+  enum spi_protocol proto)
 {
int ret;
u8 val;
@@ -954,14 +966,20 @@ static int micron_quad_enable(struct spi_nor *nor)
 
write_enable(nor);
 
-   /* set EVCR, enable quad I/O */
-   nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON;
+   /* set EVCR protocol bits */
+   nor->cmd_buf[0] = (val & ~mask) | value;
ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1, 0);
if (ret < 0) {
dev_err(nor->dev, "error while writing EVCR register\n");
return ret;
}
 
+   /* switch protocol for ALL commands */
+   nor->erase_proto = proto;
+   nor->read_proto = proto;
+   nor->write_proto = proto;
+   nor->reg_proto = proto;
+
ret = spi_nor_wait_till_ready(nor);
if (ret)
return ret;
@@ -972,14 +990,23 @@ static int micron_quad_enable(struct spi_nor *nor)
dev_err(nor->dev, "error %d reading EVCR\n", ret);
return ret;
}
-   if (val & EVCR_QUAD_EN_MICRON) {
-   dev_err(nor->dev, "Micron EVCR Quad bit not clear\n");
+   if ((val & mask) != value) {
+   dev_err(nor->dev, "Micron EVCR protocol bits not valid\n");
return -EINVAL;
}
 
return 0;
 }
 
+static inline int micron_quad_enable(struct spi_nor *nor)
+{
+   /* Clear Quad bit to enable quad mode */
+   return micron_set_protocol(nor,
+  EVCR_QUAD_EN_MICRON | EVCR_DUAL_EN_MICRON,
+  EVCR_DUAL_EN_MICRON,
+  SPI_PROTO_4_4_4);
+}
+
 static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
 {
int status;
@@ -1009,6 +1036,38 @@ static int set_quad_mode(struct spi_nor *nor, const 
struct flash_info *info)
}
 }
 
+static inline int micron_dual_enable(struct spi_nor *nor)
+{
+   /* Clear Dual bit but keep Quad bit set to enable dual mode */
+   return micron_set_protocol(nor,
+  EVCR_QUAD_EN_MICRON | EVCR_DUAL_EN_MICRON,
+  EVCR_QUAD_EN_MICRON,
+  SPI_PROTO_2_2_2);
+}
+
+static int set_dual_mode(struct spi_nor *nor, const struct flash_info *info)
+{
+   int status;
+
+   switch (JEDEC_MFR(info)) {
+   case CFI_MFR_ST:
+   status = micron_dual_enable(nor);
+   if (status) {
+   dev_err(nor->dev, "Micron dual-read not enabled\n");
+   return -EINVAL;
+   }
+   return status;
+   case CFI_MFR_MACRONIX:
+   case CFI_MFR_AMD:
+   nor->read_proto = SPI_PROTO_1_1_2;
+   break;
+   default:
+   break;
+   }
+
+   return 0;
+}
+
 static int spi_nor_check(struct spi_nor *nor)
 {
i

[PATCH linux-next v6 4/8] mtd: spi-nor: use optimized commands for read/write/erase operations

2015-09-09 Thread Cyrille Pitchen
The op codes used by the spi-nor framework are now tuned depending on the
memory manufacturer.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 156 +++---
 include/linux/mtd/spi-nor.h   |   6 ++
 2 files changed, 138 insertions(+), 24 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 4b36aada3f4c..820a2177ed5e 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -193,6 +193,8 @@ static inline int set_4byte(struct spi_nor *nor, const 
struct flash_info *info,
write_disable(nor);
 
return status;
+   case CFI_MFR_AMD:
+   return 0;
default:
/* Spansion style */
nor->cmd_buf[0] = enable << 7;
@@ -945,7 +947,7 @@ static int spansion_quad_enable(struct spi_nor *nor)
}
 
/* set read/write protocols */
-   nor->read_proto = SPI_PROTO_1_1_4;
+   nor->read_proto = SPI_PROTO_1_4_4;
nor->write_proto = SPI_PROTO_1_1_4;
 
return 0;
@@ -1059,7 +1061,7 @@ static int set_dual_mode(struct spi_nor *nor, const 
struct flash_info *info)
return status;
case CFI_MFR_MACRONIX:
case CFI_MFR_AMD:
-   nor->read_proto = SPI_PROTO_1_1_2;
+   nor->read_proto = SPI_PROTO_1_2_2;
break;
default:
break;
@@ -1068,6 +1070,130 @@ static int set_dual_mode(struct spi_nor *nor, const 
struct flash_info *info)
return 0;
 }
 
+static void macronix_set_commands(struct spi_nor *nor)
+{
+   switch (nor->flash_read) {
+   case SPI_NOR_QUAD: /* QPI mode */
+   nor->read_opcode = SPINOR_OP_READ_1_4_4;
+   break;
+
+   case SPI_NOR_DUAL:
+   nor->read_opcode = SPINOR_OP_READ_1_2_2;
+   break;
+
+   case SPI_NOR_FAST:
+   nor->read_opcode = SPINOR_OP_READ_FAST;
+   break;
+
+   case SPI_NOR_NORMAL:
+   default:
+   nor->read_opcode = SPINOR_OP_READ;
+   break;
+   }
+
+   nor->program_opcode = SPINOR_OP_PP;
+}
+
+static void micron_set_commands(struct spi_nor *nor)
+{
+   switch (nor->flash_read) {
+   case SPI_NOR_QUAD: /* Quad I/O operations */
+   nor->read_opcode = SPINOR_OP_READ_1_4_4;
+   break;
+
+   case SPI_NOR_DUAL: /* Dual I/O operations */
+   nor->read_opcode = SPINOR_OP_READ_1_2_2;
+   break;
+
+   case SPI_NOR_FAST:
+   nor->read_opcode = SPINOR_OP_READ_FAST;
+   break;
+
+   case SPI_NOR_NORMAL:
+   default:
+   nor->read_opcode = SPINOR_OP_READ;
+   break;
+   }
+
+   nor->program_opcode = SPINOR_OP_PP;
+}
+
+static void spansion_set_commands(struct spi_nor *nor,
+ const struct flash_info *info)
+{
+   bool addr_4byte = (nor->addr_width == 4);
+   struct mtd_info *mtd = nor->mtd;
+
+   switch (nor->flash_read) {
+   case SPI_NOR_QUAD:
+   if (addr_4byte) {
+   nor->read_opcode = SPINOR_OP_READ4_1_4_4;
+   nor->program_opcode = SPINOR_OP_PP_4B_1_1_4;
+   } else {
+   nor->read_opcode = SPINOR_OP_READ_1_4_4;
+   nor->program_opcode = SPINOR_OP_PP_1_1_4;
+   }
+   break;
+
+   case SPI_NOR_DUAL:
+   if (addr_4byte) {
+   nor->read_opcode = SPINOR_OP_READ4_1_2_2;
+   nor->program_opcode = SPINOR_OP_PP_4B;
+   } else {
+   nor->read_opcode = SPINOR_OP_READ_1_2_2;
+   nor->program_opcode = SPINOR_OP_PP;
+   }
+   break;
+
+   case SPI_NOR_FAST:
+   if (addr_4byte) {
+   nor->read_opcode = SPINOR_OP_READ4_FAST;
+   nor->program_opcode = SPINOR_OP_PP_4B;
+   } else {
+   nor->read_opcode = SPINOR_OP_READ_FAST;
+   nor->program_opcode = SPINOR_OP_PP;
+   }
+   break;
+
+   case SPI_NOR_NORMAL:
+   default:
+   if (addr_4byte) {
+   nor->read_opcode = SPINOR_OP_READ4;
+   nor->program_opcode = SPINOR_OP_PP_4B;
+   } else {
+   nor->read_opcode = SPINOR_OP_READ;
+   nor->program_opcode = SPINOR_OP_PP;
+   }
+   break;
+   }
+
+   if (addr_4byte) {
+   nor->erase_opcode = SPINOR_OP_SE_4B;
+   mtd->erasesize = info->sector_size;
+   }
+}
+
+static void tune_manufacturer_c

[PATCH linux-next v6 1/8] mtd: spi-nor: read JEDEC ID with multiple I/O protocols

2015-09-09 Thread Cyrille Pitchen
When their quad or dual I/O mode is enabled, Micron and Macronix spi-nor
memories don't reply to the regular Read ID (0x9f) command. Instead they
reply to a new dedicated command Read ID Multiple I/O (0xaf).

If the Read ID (0x9f) command fails (the read ID is all 1's or all 0's),
then the Read ID Multiple I/O (0xaf) is used, first with SPI 4-4-4 protocol
(supported by both Micron and Macronix memories), lately with SPI-2-2-2
protocol (supported only by Micron memories).

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 28 +++-
 include/linux/mtd/spi-nor.h   | 23 +--
 2 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index f59aedfe1462..80a0db078aaa 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -703,8 +703,9 @@ static const struct flash_info spi_nor_ids[] = {
 
 static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
 {
-   int tmp;
+   int i, tmp;
u8  id[SPI_NOR_MAX_ID_LEN];
+   enum spi_protocol   proto[2] = {SPI_PROTO_4_4_4, SPI_PROTO_2_2_2};
const struct flash_info *info;
 
tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
@@ -713,6 +714,25 @@ static const struct flash_info *spi_nor_read_id(struct 
spi_nor *nor)
return ERR_PTR(tmp);
}
 
+   /* Special case for Micron/Macronix qspi nor. */
+   for (i = 0; i < ARRAY_SIZE(proto); ++i) {
+   if (!((id[0] == 0xff && id[1] == 0xff && id[2] == 0xff) ||
+ (id[0] == 0x00 && id[1] == 0x00 && id[2] == 0x00)))
+   break;
+
+   nor->erase_proto = proto[i];
+   nor->read_proto = proto[i];
+   nor->write_proto = proto[i];
+   nor->reg_proto = proto[i];
+   tmp = nor->read_reg(nor, SPINOR_OP_MIO_RDID,
+   id, SPI_NOR_MAX_ID_LEN);
+   if (tmp < 0) {
+   dev_dbg(nor->dev,
+   " error %d reading JEDEC ID (MULTI IO)\n", tmp);
+   return ERR_PTR(tmp);
+   }
+   }
+
for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) {
info = _nor_ids[tmp];
if (info->id_len) {
@@ -1013,6 +1033,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
if (ret)
return ret;
 
+   /* Reset SPI protocol for all commands */
+   nor->erase_proto = SPI_PROTO_1_1_1;
+   nor->read_proto = SPI_PROTO_1_1_1;
+   nor->write_proto = SPI_PROTO_1_1_1;
+   nor->reg_proto = SPI_PROTO_1_1_1;
+
if (name)
info = spi_nor_match_id(name);
/* Try to auto-detect if chip name wasn't specified or not found */
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index e5409524bb0a..66a5f144728a 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -57,8 +57,9 @@
 #define SPINOR_OP_BRWR 0x17/* Bank register write */
 
 /* Used for Micron flashes only. */
-#define SPINOR_OP_RD_EVCR  0x65/* Read EVCR register */
-#define SPINOR_OP_WD_EVCR  0x61/* Write EVCR register */
+#define SPINOR_OP_MIO_RDID 0xaf/* Multiple I/O Read JEDEC ID */
+#define SPINOR_OP_RD_EVCR  0x65/* Read EVCR register */
+#define SPINOR_OP_WD_EVCR  0x61/* Write EVCR register */
 
 /* Status Register bits. */
 #define SR_WIP 1   /* Write in progress */
@@ -87,6 +88,16 @@ enum read_mode {
SPI_NOR_QUAD,
 };
 
+enum spi_protocol {
+   SPI_PROTO_1_1_1,/* SPI */
+   SPI_PROTO_1_1_2,/* Dual Output */
+   SPI_PROTO_1_1_4,/* Quad Output */
+   SPI_PROTO_1_2_2,/* Dual IO */
+   SPI_PROTO_1_4_4,/* Quad IO */
+   SPI_PROTO_2_2_2,/* Dual Command */
+   SPI_PROTO_4_4_4,/* Quad Command */
+};
+
 /**
  * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer
  * @wren:  command for "Write Enable", or 0x00 for not required
@@ -142,6 +153,10 @@ enum spi_nor_option_flags {
  * @sst_write_second:  used by the SST write operation
  * @flags: flag options for the current SPI-NOR (SNOR_F_*)
  * @cfg:   used by the read_xfer/write_xfer
+ * @erase_proto:   the SPI protocol used by erase operations
+ * @read_proto:the SPI protocol used by read operations
+ * @write_proto:   the SPI protocol used by write operations
+ * @reg_proto  the SPI protocol used by read_reg/write_reg operations
  * @cmd_buf:   used by the write_reg
  * @prepare:   

[PATCH linux-next v6 6/8] mtd: spi-nor: allow to tune the number of dummy cycles

2015-09-09 Thread Cyrille Pitchen
The number of dummy cycles used during Fast Read commands can be reduced
to improve transfer performances. Each manufacturer has a dedicated set of
registers to provide the memory with the exact number of dummy cycles it
should expect. Both the memory and the (Q)SPI controller must agree on
this number of dummy cycles.

The number of dummy cycles can be found into the memory datasheet and
mostly depends on the SPI clock frequency, the Fast Read op code and the
Single/Dual Data Rate mode.

Probing JEDEC Serial Flash Discoverable Parameters (SFDP) tables would
only provide the driver with a high enough number of dummy cycles for each
Fast Read command to be used for all clock frequencies: this solution
would not be optimized.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 102 ++
 include/linux/mtd/spi-nor.h   |   2 +
 2 files changed, 85 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 820a2177ed5e..7405a1450dd1 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -121,24 +121,6 @@ static int read_cr(struct spi_nor *nor)
 }
 
 /*
- * Dummy Cycle calculation for different type of read.
- * It can be used to support more commands with
- * different dummy cycle requirements.
- */
-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
-{
-   switch (nor->flash_read) {
-   case SPI_NOR_FAST:
-   case SPI_NOR_DUAL:
-   case SPI_NOR_QUAD:
-   return 8;
-   case SPI_NOR_NORMAL:
-   return 0;
-   }
-   return 0;
-}
-
-/*
  * Write status register 1 byte
  * Returns negative if error occurred.
  */
@@ -1194,6 +1176,86 @@ static void tune_manufacturer_commands(struct spi_nor 
*nor,
}
 }
 
+static int micron_set_dummy_cycles(struct spi_nor *nor)
+{
+   int ret;
+   u8 val, mask;
+
+   /* Read the Volatile Configuration Register (VCR). */
+   ret = nor->read_reg(nor, SPINOR_OP_RD_VCR, , 1);
+   if (ret < 0) {
+   dev_err(nor->dev, "error %d reading VCR\n", ret);
+   return ret;
+   }
+
+   write_enable(nor);
+
+   /* Update the number of dummy into the VCR. */
+   mask = GENMASK(7, 4);
+   val &= ~mask;
+   val |= (nor->read_dummy << 4) & mask;
+   ret = nor->write_reg(nor, SPINOR_OP_WR_VCR, , 1, 0);
+   if (ret < 0) {
+   dev_err(nor->dev, "error while writing VCR register\n");
+   return ret;
+   }
+
+   ret = spi_nor_wait_till_ready(nor);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
+/*
+ * Dummy Cycle calculation for different type of read.
+ * It can be used to support more commands with
+ * different dummy cycle requirements.
+ */
+static int spi_nor_read_dummy_cycles(struct spi_nor *nor,
+const struct flash_info *info)
+{
+   struct device_node *np = nor->dev->of_node;
+   struct device *dev = nor->dev;
+   u32 num_dummy_cycles;
+
+   if (np && !of_property_read_u32(np, "m25p,num-dummy-cycles",
+   _dummy_cycles)) {
+   nor->read_dummy = num_dummy_cycles;
+
+   /*
+* This switch block might be moved at the end of the function,
+* once nor->read_dummy has been set, but it was not tested with
+* all Micron memories.
+* Now the "m25p,num-dummy-cycles" property needs to be
+* explicitly set in the device tree so the switch statement is
+* executed. This should avoid unwanted side effects and keep
+* backward compatibility.
+*/
+   switch (JEDEC_MFR(info)) {
+   case CFI_MFR_ST:
+   return micron_set_dummy_cycles(nor);
+   default:
+   dev_warn(dev,
+"Tuning of the number of dummy cycles is not 
implemented for spi-nor of this manufacturer,\n"
+"ignoring the DT property value and falling 
back to the framework default settings.\n");
+   break;
+   }
+   }
+
+   /* Fallback to legacy code. */
+   switch (nor->flash_read) {
+   case SPI_NOR_FAST:
+   case SPI_NOR_DUAL:
+   case SPI_NOR_QUAD:
+   nor->read_dummy = 8;
+   case SPI_NOR_NORMAL:
+   nor->read_dummy = 0;
+   }
+
+   return 0;
+}
+
 static int spi_nor_check(struct spi_nor *nor)
 {
if (!nor->dev || !nor->read || !nor->write ||
@@ -1387,7 +1449,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
/* Tune read, page pro

[PATCH linux-next v6 5/8] Documentation: mtd: add a DT property to set the number of dummy cycles

2015-09-09 Thread Cyrille Pitchen
Depending on the SPI clock frequency, the Fast Read op code and the
Single/Dual Data Rate mode, the number of dummy cycles can be tuned to
improve transfer speed.
The actual number of dummy cycles is specific for each memory model and is
provided by the manufacturer thanks to the memory datasheet.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt 
b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
index 2bee68103b01..4387567d8024 100644
--- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
+++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
@@ -19,6 +19,11 @@ Optional properties:
all chips and support for it can not be detected at runtime.
Refer to your chips' datasheet to check if this is supported
by your chip.
+- m25p,num-dummy-cycles : Set the number of dummy cycles for Fast Read 
commands.
+  Depending on the manufacturer additional dedicated
+  commands are sent to the flash memory so the
+  controller and the memory can agree on the number of
+  dummy cycles to use.
 
 Example:
 
@@ -29,4 +34,5 @@ Example:
reg = <0>;
spi-max-frequency = <4000>;
m25p,fast-read;
+   m25p,num-dummy-cycles = <8>;
};
-- 
1.8.2.2

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


[PATCH linux-next v6 8/8] mtd: atmel-quadspi: add driver for Atmel QSPI controller

2015-09-09 Thread Cyrille Pitchen
This driver add support to the new Atmel QSPI controller embedded into
sama5d2x SoCs. It expects a NOR memory to be connected to the QSPI
controller.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi-nor/Kconfig |   7 +
 drivers/mtd/spi-nor/Makefile|   1 +
 drivers/mtd/spi-nor/atmel-quadspi.c | 889 
 3 files changed, 897 insertions(+)
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 89bf4c1faa2b..7a3d55429550 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -29,6 +29,13 @@ config SPI_FSL_QUADSPI
  This controller does not support generic SPI. It only supports
  SPI NOR.
 
+config SPI_ATMEL_QUADSPI
+   tristate "Atmel Quad SPI Controller"
+   depends on OF && HAS_DMA && (ARCH_AT91 || COMPILE_TEST)
+   help
+ This enables support for the Quad SPI controller in master mode.
+ We only connect the NOR to this controller now.
+
 config SPI_NXP_SPIFI
tristate "NXP SPI Flash Interface (SPIFI)"
depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index e5ef8582..f5d23d7379bb 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_MTD_SPI_NOR)  += spi-nor.o
 obj-$(CONFIG_SPI_FSL_QUADSPI)  += fsl-quadspi.o
+obj-$(CONFIG_SPI_ATMEL_QUADSPI)+= atmel-quadspi.o
 obj-$(CONFIG_SPI_NXP_SPIFI)+= nxp-spifi.o
diff --git a/drivers/mtd/spi-nor/atmel-quadspi.c 
b/drivers/mtd/spi-nor/atmel-quadspi.c
new file mode 100644
index ..dc0c1d8293d5
--- /dev/null
+++ b/drivers/mtd/spi-nor/atmel-quadspi.c
@@ -0,0 +1,889 @@
+/*
+ * Driver for Atmel QSPI Controller
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen <cyrille.pitc...@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This driver is based on drivers/mtd/spi-nor/fsl-quadspi.c from Freescale.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+/* QSPI register offsets */
+#define QSPI_CR  0x  /* Control Register */
+#define QSPI_MR  0x0004  /* Mode Register */
+#define QSPI_RD  0x0008  /* Receive Data Register */
+#define QSPI_TD  0x000c  /* Transmit Data Register */
+#define QSPI_SR  0x0010  /* Status Register */
+#define QSPI_IER 0x0014  /* Interrupt Enable Register */
+#define QSPI_IDR 0x0018  /* Interrupt Disable Register */
+#define QSPI_IMR 0x001c  /* Interrupt Mask Register */
+#define QSPI_SCR 0x0020  /* Serial Clock Register */
+
+#define QSPI_IAR 0x0030  /* Instruction Address Register */
+#define QSPI_ICR 0x0034  /* Instruction Code Register */
+#define QSPI_IFR 0x0038  /* Instruction Frame Register */
+
+#define QSPI_SMR 0x0040  /* Scrambling Mode Register */
+#define QSPI_SKR 0x0044  /* Scrambling Key Register */
+
+#define QSPI_WPMR0x00E4  /* Write Protection Mode Register */
+#define QSPI_WPSR0x00E8  /* Write Protection Status Register */
+
+#define QSPI_VERSION 0x00FC  /* Version Register */
+
+
+/* Bitfields in QSPI_CR (Control Register) */
+#define QSPI_CR_QSPIEN  BIT(0)
+#define QSPI_CR_QSPIDIS BIT(1)
+#define QSPI_CR_SWRST   BIT(7)
+#define QSPI_CR_LASTXFERBIT(24)
+
+/* Bitfields in QSPI_MR (Mode Register) */
+#define QSPI_MR_SSM BIT(0)
+#define QSPI_MR_LLB BIT(1)
+#define QSPI_MR_WDRBT   BIT(2)
+#define QSPI_MR_SMRMBIT(3)
+#define QSPI_MR_CSMODE_MASK GENMASK(5, 4)
+#define QSPI_MR_CSMODE_NOT_RELOADED (0 << 4)
+#define QSPI_MR_CSMODE_LASTXFER (1 << 4)
+#define QSPI_MR_CSMODE_SYSTEMATICALLY   (2 << 4)
+#define QSPI_MR_NBBITS_MASK GENMASK(11, 8)
+#define QSPI_MR_NBBITS(n)   n) - 8) << 8) & 
QSPI_MR_NBBITS_MASK)
+#define QSPI_MR_DLYBCT_MASK GENMASK(23, 16)
+#define QSPI_MR_DLYBCT(n)   (((n) << 16) & QSPI_MR_DLYBCT_MASK)
+#define QSPI_MR_DLYCS_MASK

[PATCH linux-next v6 7/8] Documentation: atmel-quadspi: add binding file for Atmel QSPI driver

2015-09-09 Thread Cyrille Pitchen
This patch documents the DT bindings for the driver of the Atmel QSPI
controller embedded inside sama5d2x SoCs.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
Acked-by: Nicolas Ferre <nicolas.fe...@atmel.com>
Acked-by: Marek Vasut <ma...@denx.de>
Acked-by: Rob Herring <r...@kernel.org>
---
 .../devicetree/bindings/mtd/atmel-quadspi.txt  | 29 ++
 1 file changed, 29 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt

diff --git a/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt 
b/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
new file mode 100644
index ..0b8d545bb198
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
@@ -0,0 +1,29 @@
+* Atmel Quad Serial Peripheral Interface (QSPI)
+
+Required properties:
+- compatible: should be "atmel,sama5d2-qspi"
+- reg:the first contains the register location and length,
+  the second contains the memory mapping address and length
+- interrupts: should contain the interrupt for the device
+- clocks: the phandle of the clock needed by the QSPI controller
+- #address-cells: should be <1>
+- #size-cells:should be <0>
+
+Example:
+
+spi@f002 {
+   compatible = "atmel,sama5d2-qspi";
+   reg = <0xf002 0x100>,
+ <0xd000 0x800>;
+   interrupts = <52 IRQ_TYPE_LEVEL_HIGH 7>;
+   clocks = <_clk>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   pinctrl-names = "default";
+   pinctrl-0 = <_spi0_default>;
+   status = "okay";
+
+   m25p80@0 {
+   ...
+   };
+};
-- 
1.8.2.2

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


Re: [PATCH linux-next v9 2/3] mfd: devicetree: add bindings for Atmel Flexcom

2015-09-09 Thread Cyrille Pitchen
Hi Rob,

Le 09/09/2015 01:40, Rob Herring a écrit :
> On 09/01/2015 09:46 AM, Cyrille Pitchen wrote:
>> This patch documents the DT bindings for the Atmel Flexcom which will be
>> introduced by sama5d2x SoCs. These bindings will be used by the actual
>> Flexcom driver to be sent in another patch.
>>
>> Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
>> Acked-by: Boris Brezillon <boris.brezil...@free-electrons.com>
>> Acked-by: Alexandre Belloni <alexandre.bell...@free-electrons.com>
> 
> A few comments, but in general looks fine.
> 
>> ---
>>  .../devicetree/bindings/mfd/atmel-flexcom.txt  | 67 
>> ++
>>  1 file changed, 67 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt 
>> b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
>> new file mode 100644
>> index ..fc3511e41542
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
>> @@ -0,0 +1,67 @@
>> +* Device tree bindings for Atmel Flexcom (Flexible Serial Communication 
>> Unit)
>> +
>> +The Atmel Flexcom is just a wrapper which embeds a SPI controller, an I2C
>> +controller and an USART. Only one function can be used at a time and is 
>> chosen
>> +at boot time according to the device tree.
> 
> Doesn't the board design choose (unless pins go to a header)?
> 

The function may be chosen once for all by the board design but if we take the
sama5d2 xplained board as an example, most Flexcoms output their pins to
headers.

>> +
>> +Required properties:
>> +- compatible:   Should be "atmel,sama5d2-flexcom"
>> +- reg:  Should be the offset/length value for Flexcom 
>> dedicated
>> +I/O registers (without USART, TWI or SPI registers).
>> +- clocks:   Should be the Flexcom peripheral clock from PMC.
>> +- #address-cells:   Should be <1>
>> +- #size-cells:  Should be <1>
>> +- ranges:   Should be one range for the full I/O register region
>> +(including USART, TWI and SPI registers).
>> +- atmel,flexcom-mode:   Should be one of the 3 following macros as 
>> defined in
>> +include/dt-bindings/mfd/atmel-flexcom.h:
>> +- ATMEL_FLEXCOM_MODE_USART for USART
>> +- ATMEL_FLEXCOM_MODE_SPI for SPI
>> +- ATMEL_FLEXCOM_MODE_TWI for I2C
>> +
>> +Required child:
>> +a single child device of type matching the "atmel,flexcom-mode" property.
> 
> Okay, but why not allow all children and use "status"?
> 

That is exactly what was proposed in v6 of this series: allow more than one
child so possibly all children but only one "available" child (status = 
"okay").

The Flexocm driver still needs to find out the type of device of this
available child to know which function is to be enabled (USART, I2C or SPI).
So the "compatible" attribute was parsed using strstr() to search on of the
patterns "usart", "spi" or "i2c".

However the use of strstr() was discussed to know whether the driver should
looks for a partial or an exact match of the "compatible" string.
An exact match would require to keep the Flexcom driver synchonized with the
3 other drivers every time one of them introduces a new compatibility string,
which whould have made every driver more difficult to maintain by creating a
useless dependency.
So this implementation relying on the "compatible" attribute was abandoned.

To sum up, no other reliable (and simple) means to guess/extact the device
type from its DT node was found so we got back to the "atmel,flexcom-mode"
property.

>> +
>> +The reg property of this child should be:
>> +- <0x200 0x200> for USART
>> +- <0x400 0x200> for SPI
>> +- <0x600 0x200> for I2C
>> +
>> +The phandle provided by the clocks property of the child is the same as one 
>> for
>> +the Flexcom parent.
>> +
>> +Other properties remain unchanged. See documentation of the respective 
>> device:
>> +- ../serial/atmel-usart.txt
>> +- ../spi/spi_atmel.txt
>> +- ../i2c/i2c-at91.txt
>> +
>> +Example:
>> +
>> +flexcom@f8034000 {
>> +compatible = "atmel,sama5d2-flexcom";
>> +reg = <0xf8034000 0x200>;
>> +clocks = <_clk>;
>> +#address-cells = <1>;
>> +#size-cells

Re: [PATCH linux-next v6 1/8] mtd: spi-nor: read JEDEC ID with multiple I/O protocols

2015-09-09 Thread Cyrille Pitchen
Hi Marek,

Le 09/09/2015 15:59, Marek Vasut a écrit :
> On Wednesday, September 09, 2015 at 03:24:11 PM, Cyrille Pitchen wrote:
>> When their quad or dual I/O mode is enabled, Micron and Macronix spi-nor
>> memories don't reply to the regular Read ID (0x9f) command. Instead they
>> reply to a new dedicated command Read ID Multiple I/O (0xaf).
>>
>> If the Read ID (0x9f) command fails (the read ID is all 1's or all 0's),
>> then the Read ID Multiple I/O (0xaf) is used, first with SPI 4-4-4 protocol
>> (supported by both Micron and Macronix memories), lately with SPI-2-2-2
>> protocol (supported only by Micron memories).
>>
>> Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
>> ---
>>  drivers/mtd/spi-nor/spi-nor.c | 28 +++-
>>  include/linux/mtd/spi-nor.h   | 23 +--
>>  2 files changed, 48 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
>> index f59aedfe1462..80a0db078aaa 100644
>> --- a/drivers/mtd/spi-nor/spi-nor.c
>> +++ b/drivers/mtd/spi-nor/spi-nor.c
>> @@ -703,8 +703,9 @@ static const struct flash_info spi_nor_ids[] = {
>>
>>  static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
>>  {
>> -int tmp;
>> +int i, tmp;
>>  u8  id[SPI_NOR_MAX_ID_LEN];
>> +enum spi_protocol   proto[2] = {SPI_PROTO_4_4_4, SPI_PROTO_2_2_2};
>>  const struct flash_info *info;
>>
>>  tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
>> @@ -713,6 +714,25 @@ static const struct flash_info *spi_nor_read_id(struct
>> spi_nor *nor) return ERR_PTR(tmp);
>>  }
>>
>> +/* Special case for Micron/Macronix qspi nor. */
>> +for (i = 0; i < ARRAY_SIZE(proto); ++i) {
>> +if (!((id[0] == 0xff && id[1] == 0xff && id[2] == 0xff) ||
>> +  (id[0] == 0x00 && id[1] == 0x00 && id[2] == 0x00)))
>> +break;
>> +
>> +nor->erase_proto = proto[i];
>> +nor->read_proto = proto[i];
>> +nor->write_proto = proto[i];
>> +nor->reg_proto = proto[i];
>> +tmp = nor->read_reg(nor, SPINOR_OP_MIO_RDID,
>> +id, SPI_NOR_MAX_ID_LEN);
>> +if (tmp < 0) {
>> +dev_dbg(nor->dev,
>> +" error %d reading JEDEC ID (MULTI IO)\n", tmp);
> 
> Don't you have one space too much in front of the " error" ?
> 

Probably, I've just copied and pasted the dev_dbg() message few lines above when
the regular SPINOR_OP_RDID fails, then appended the "(MULTI IO)" string to make
think consistent but I don't mind removing the leading space.

tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
if (tmp < 0) {
dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp);
return ERR_PTR(tmp);
}

>> +return ERR_PTR(tmp);
>> +}
>> +}
>> +
>>  for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) {
>>  info = _nor_ids[tmp];
>>  if (info->id_len) {
> 
> [...]
> 

Best Regards,

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


Re: [PATCH linux-next v9 0/3] mfd: flexcom: add a driver for Flexcom

2015-09-08 Thread Cyrille Pitchen
Hi all,

Le 01/09/2015 16:46, Cyrille Pitchen a écrit :
> ChangeLog
> 
> v9:
> - go back to v5 (use the new "atmel,flexcom-mode" DT property).
> - fix the name of the spi node in the DT example: from spi@f8034400 to
>   spi@400
> - align the fields of the struct platform_driver atmel_flexcom_driver as
>   suggested by Lee Jones.
> 
[...]

Are there any remaining blocking points for this series ?

Best Regards,

Cyrille

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


Re: [PATCH linux-next v5 1/5] mtd: spi-nor: notify (Q)SPI controller about protocol change

2015-09-08 Thread Cyrille Pitchen
Hi Jonas,

taking your comments into account I'm about to test a new series with
additional patches to handle the Read ID command in multiple I/O protocols and
relying on new members in the struct spi_nor:

 * @erase_proto:the SPI protocol used by erase operations
 * @read_proto: the SPI protocol used by read operations
 * @write_proto:the SPI protocol used by write operations
 * @reg_proto   the SPI protocol used by read_reg/write_reg operations

enum spi_protocol   erase_proto;
enum spi_protocol   read_proto;
enum spi_protocol   write_proto;
enum spi_protocol   reg_proto;

This way, the read(), write(), erase(), read_reg() and write_reg() hooks can
check the relevant protocol member so the spi-nor framework doesn't need to
call spi_nor_set_protocol() before any command.

Also the op codes for read, page program and erase commands will be tuned
depending on the memory manufacturer and the selected SPI protocol.

I'm likely to publish this new series tomorrow after my tests on a Micron
memory.

Best Regards,

Cyrille
 

Le 31/08/2015 21:22, Jonas Gorski a écrit :
> Hi,
> 
> On Thu, Aug 27, 2015 at 11:51 AM, Cyrille Pitchen
> <cyrille.pitc...@atmel.com> wrote:
>> Hi Jonas,
>>
>> Le 26/08/2015 16:02, Jonas Gorski a écrit :
>>> On Wed, Aug 26, 2015 at 2:30 PM, Cyrille Pitchen
>>> <cyrille.pitc...@atmel.com> wrote:
>>>> Once the Quad SPI mode has been enabled on a Micron flash memory, this
>>>> device expects ALL the following commands to use the SPI 4-4-4 protocol.
>>>> The (Q)SPI controller needs to be notified about the protocol change so it
>>>> can adapt and keep on dialoging with the Micron memory.
>>>
>>> Doesn't that mean you need to disable quad mode on removal? Else the
>>> following will break/fail:
>>>
>>> insmod atmel-quadspi.ko ~> spi-nor attaches -> sees micron -> enables quad 
>>> mode
>>> rmmod atmel-quadspi.ko ~> spi-nor detaches
>>> insmod atmel-quadspi.ko ~> spi-nor attaches -> fails to read the id
>>> because flash is still in quad mode.
>>>
>>
>> Indeed you're right such an issue does exist. So as you said one solution
>> could be create a new function to "clean" what have been done by 
>> spi_nor_scan()
>> then call it from remove() function of each driver calling spi_nor_scan() 
>> from
>> its probe().
>> However we could also enhance the probing of the memory. It is true that 
>> Micron
>> spi nor memories only accept SPI 4-4-4 commands once switched in quad mode 
>> but
>> actually they also provide a new command for this purpose:
>> "Multiple I/O Read ID" (0xAF).
>> Hence we could first try to probe using the regular Read ID (0x9F) command 
>> then
>> change the protocol, for instance to SPI 4-4-4, and try the 0xAF command.
>> I don't think all combinations for command/protocol need to be tested: for
>> Micron memories, their datasheets claim the 0x9F command is only supported in
>> "extended spi mode" so for the SPI 1-1-1 protocol whereas the 0xAF command
>> only works in dual or quad modes.
>> On the other hand Spansion memories still reply to the regular 0x9F command 
>> in
>> SPI 1-1-1 protocol even after their quad mode had been enabled.
>> For other manufacturers, well... I don't know!
> 
> At least from the two spansion datasheets I looked at, there is no 2_
> or 4_ mode for spansion flashes, and the quad mode only enables the
> 1_x_4 commands, where as on micron the 1_x_4 commands are always
> available, and you only need to switch to DIO or QIO if you want to
> use 2_2_2 or 4_4_4.
> 
> The question is how to detect if the READID command failed. Hopefully
> it will result in an invalid command, and we get 0xff... (or 0x00...)
> for the the id. And from there on we can first test 4_4_4 MIORDID (so
> it won't a a full command on a DIO-enabled flash), and if that fails,
> 2_2_2. We need to tell the spi-nor controller to send these
> accordingly though. I wonder if it might not be better to pass the
> c_a_d as an additional parameter to the read_reg/write_reg etc call
> backs, because they might change depending on the command used. E.g.
> when using SPI_NOR_QUAD, we might want to make use of the quad page
> program command (which is 1_1_4), but there is no 1_1_2 version, so we
> cannot rely on a global "protocol" member for that, unless we want to
> do a set_protocol before every command.
> 
>>
>> Some of the advantages of the probe solution as compared to the remove one 
>> are:
>> - we don't need to patch all drivers us

[PATCH linux-next v9 1/3] mfd: atmel-flexcom: create include file with macros used by DT bindings

2015-09-01 Thread Cyrille Pitchen
This patch defines some macros to be used as value for the
"atmel,flexcom-mode" DT property. This value is then written into
the Operating Mode (OPMODE) bit field of the Flexcom Mode Register.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 include/dt-bindings/mfd/atmel-flexcom.h | 16 
 1 file changed, 16 insertions(+)
 create mode 100644 include/dt-bindings/mfd/atmel-flexcom.h

diff --git a/include/dt-bindings/mfd/atmel-flexcom.h 
b/include/dt-bindings/mfd/atmel-flexcom.h
new file mode 100644
index ..6728f2851b4d
--- /dev/null
+++ b/include/dt-bindings/mfd/atmel-flexcom.h
@@ -0,0 +1,16 @@
+/*
+ * This header provides macros for Atmel Flexcom DT bindings.
+ *
+ * Copyright (C) 2015 Cyrille Pitchen <cyrille.pitc...@atmel.com>
+ *
+ * GPLv2 only
+ */
+
+#ifndef __DT_BINDINGS_ATMEL_FLEXCOM_H__
+#define __DT_BINDINGS_ATMEL_FLEXCOM_H__
+
+#define ATMEL_FLEXCOM_MODE_USART   1
+#define ATMEL_FLEXCOM_MODE_SPI 2
+#define ATMEL_FLEXCOM_MODE_TWI 3
+
+#endif /* __DT_BINDINGS_ATMEL_FLEXCOM_H__ */
-- 
1.8.2.2

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


[PATCH linux-next v9 3/3] mfd: atmel-flexcom: add a driver for Atmel Flexible Serial Communication Unit

2015-09-01 Thread Cyrille Pitchen
This driver supports the new Atmel Flexcom. The Flexcom is a wrapper which
integrates one SPI controller, one I2C controller and one USART. Only one
function can be enabled at a time. This driver selects the function once
for all, when the Flexcom is probed, according to the value of the new
"atmel,flexcom-mode" device tree property.

This driver has chosen to present the Flexcom to the system as a MFD so
the implementation is seamless for the existing Atmel SPI, I2C and USART
drivers.

Also the Flexcom embeds FIFOs: the latest patches of the SPI, I2C and
USART drivers take advantage of this new feature.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
Acked-by: Boris Brezillon <boris.brezil...@free-electrons.com>
Acked-by: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.fe...@atmel.com>
---
 drivers/mfd/Kconfig |  11 +
 drivers/mfd/Makefile|   1 +
 drivers/mfd/atmel-flexcom.c | 104 
 3 files changed, 116 insertions(+)
 create mode 100644 drivers/mfd/atmel-flexcom.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 99d63675f073..87e84e7c71da 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -60,6 +60,17 @@ config MFD_AAT2870_CORE
  additional drivers must be enabled in order to use the
  functionality of the device.
 
+config MFD_ATMEL_FLEXCOM
+   tristate "Atmel Flexcom (Flexible Serial Communication Unit)"
+   select MFD_CORE
+   depends on OF
+   help
+ Select this to get support for Atmel Flexcom. This is a wrapper
+ which embeds a SPI controller, a I2C controller and a USART. Only
+ one function can be used at a time. The choice is done at boot time
+ by the probe function of this MFD driver according to a device tree
+ property.
+
 config MFD_ATMEL_HLCDC
tristate "Atmel HLCDC (High-end LCD Controller)"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index a59e3fcc8626..f2383e0d1760 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -164,6 +164,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
 obj-$(CONFIG_TPS65911_COMPARATOR)  += tps65911-comparator.o
 obj-$(CONFIG_MFD_TPS65090) += tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
+obj-$(CONFIG_MFD_ATMEL_FLEXCOM)+= atmel-flexcom.o
 obj-$(CONFIG_MFD_ATMEL_HLCDC)  += atmel-hlcdc.o
 obj-$(CONFIG_MFD_INTEL_LPSS)   += intel-lpss.o
 obj-$(CONFIG_MFD_INTEL_LPSS_PCI)   += intel-lpss-pci.o
diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
new file mode 100644
index ..e8e67be6b493
--- /dev/null
+++ b/drivers/mfd/atmel-flexcom.c
@@ -0,0 +1,104 @@
+/*
+ * Driver for Atmel Flexcom
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen <cyrille.pitc...@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* I/O register offsets */
+#define FLEX_MR0x0 /* Mode Register */
+#define FLEX_VERSION   0xfc/* Version Register */
+
+/* Mode Register bit fields */
+#define FLEX_MR_OPMODE_OFFSET  (0)  /* Operating Mode */
+#define FLEX_MR_OPMODE_MASK(0x3 << FLEX_MR_OPMODE_OFFSET)
+#define FLEX_MR_OPMODE(opmode) (((opmode) << FLEX_MR_OPMODE_OFFSET) &  \
+FLEX_MR_OPMODE_MASK)
+
+
+static int atmel_flexcom_probe(struct platform_device *pdev)
+{
+   struct device_node *np = pdev->dev.of_node;
+   struct clk *clk;
+   struct resource *res;
+   void __iomem *base;
+   u32 opmode;
+   int err;
+
+   err = of_property_read_u32(np, "atmel,flexcom-mode", );
+   if (err)
+   return err;
+
+   if (opmode < ATMEL_FLEXCOM_MODE_USART ||
+   opmode > ATMEL_FLEXCOM_MODE_TWI)
+   return -EINVAL;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(base))
+   return PTR_ERR(base);
+
+   clk = devm_clk_get(>dev, NULL);
+   if (IS_ERR(clk))
+   return PTR_ERR(clk);
+
+   err = clk_prepare_enable(clk);
+   if (err)
+ 

[PATCH linux-next v9 2/3] mfd: devicetree: add bindings for Atmel Flexcom

2015-09-01 Thread Cyrille Pitchen
This patch documents the DT bindings for the Atmel Flexcom which will be
introduced by sama5d2x SoCs. These bindings will be used by the actual
Flexcom driver to be sent in another patch.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
Acked-by: Boris Brezillon <boris.brezil...@free-electrons.com>
Acked-by: Alexandre Belloni <alexandre.bell...@free-electrons.com>
---
 .../devicetree/bindings/mfd/atmel-flexcom.txt  | 67 ++
 1 file changed, 67 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt

diff --git a/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt 
b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
new file mode 100644
index ..fc3511e41542
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
@@ -0,0 +1,67 @@
+* Device tree bindings for Atmel Flexcom (Flexible Serial Communication Unit)
+
+The Atmel Flexcom is just a wrapper which embeds a SPI controller, an I2C
+controller and an USART. Only one function can be used at a time and is chosen
+at boot time according to the device tree.
+
+Required properties:
+- compatible:  Should be "atmel,sama5d2-flexcom"
+- reg: Should be the offset/length value for Flexcom dedicated
+   I/O registers (without USART, TWI or SPI registers).
+- clocks:  Should be the Flexcom peripheral clock from PMC.
+- #address-cells:  Should be <1>
+- #size-cells: Should be <1>
+- ranges:  Should be one range for the full I/O register region
+   (including USART, TWI and SPI registers).
+- atmel,flexcom-mode:  Should be one of the 3 following macros as defined in
+   include/dt-bindings/mfd/atmel-flexcom.h:
+   - ATMEL_FLEXCOM_MODE_USART for USART
+   - ATMEL_FLEXCOM_MODE_SPI for SPI
+   - ATMEL_FLEXCOM_MODE_TWI for I2C
+
+Required child:
+a single child device of type matching the "atmel,flexcom-mode" property.
+
+The reg property of this child should be:
+- <0x200 0x200> for USART
+- <0x400 0x200> for SPI
+- <0x600 0x200> for I2C
+
+The phandle provided by the clocks property of the child is the same as one for
+the Flexcom parent.
+
+Other properties remain unchanged. See documentation of the respective device:
+- ../serial/atmel-usart.txt
+- ../spi/spi_atmel.txt
+- ../i2c/i2c-at91.txt
+
+Example:
+
+flexcom@f8034000 {
+   compatible = "atmel,sama5d2-flexcom";
+   reg = <0xf8034000 0x200>;
+   clocks = <_clk>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0x0 0xf8034000 0x800>;
+   atmel,flexcom-mode = ;
+
+   spi@400 {
+   compatible = "atmel,at91rm9200-spi";
+   reg = <0x400 0x200>;
+   interrupts = <19 IRQ_TYPE_LEVEL_HIGH 7>;
+   pinctrl-names = "default";
+   pinctrl-0 = <_flx0_default>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   clocks = <_clk>;
+   clock-names = "spi_clk";
+   atmel,fifo-size = <32>;
+
+   mtd_dataflash@0 {
+   compatible = "atmel,at25f512b";
+   reg = <0>;
+   spi-max-frequency = <2000>;
+   };
+   };
+};
-- 
1.8.2.2

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


[PATCH linux-next v9 0/3] mfd: flexcom: add a driver for Flexcom

2015-09-01 Thread Cyrille Pitchen
ChangeLog

v9:
- go back to v5 (use the new "atmel,flexcom-mode" DT property).
- fix the name of the spi node in the DT example: from spi@f8034400 to
  spi@400
- align the fields of the struct platform_driver atmel_flexcom_driver as
  suggested by Lee Jones.

v8:
- fix the name of the spi node in the DT example: from spi@f8034400 to
  spi@2,0
- use the return code of op_property_read_u32_index() instead of -EINVAL
  to report error.
- add Acked-by from Nicolas Ferre

v7:
- read the operating mode from the very first u32 of the reg property from
  the first available child node (should be unique).
- update the DT bindings documentation accordingly.

v6:
- select the operating mode according to the "compatible" DT property of
  the first available child node (should be unique).
- remove the "atmel,flexcom-mode" DT property so the need of a header file
  defining macros for the possible values of this deprecated property.

v5:
- create a header file containing macros used by DT bindings
- use numeric constants instead of strings to select the Flexcom mode
- change the license to "GPL v2"
- update the DT binding documentation to make it more readable and add
  references to USART, SPI and I2C DT binding documentations. remove the
  useless label in the Example section.
- change the register prefix from FX_ to FLEX_ to match the Flexcom
  programmer datasheet.
- rename some variables to make them more understandable.

v4:
- check clk_prepare_enable() return code in atmel_flexcom_probe()
- add a commit message to the DT binding patch

v3:
- remove MODULE_ALIAS()
- add Acked-by from Boris Brezillon and Alexandre Belloni

v2:
- enhance the documentation of DT bindings and change the way the "ranges"
  property is used.
- replace __raw_readl() and __raw_writel() by readl() and writel().
- change the module license to "GPL" for v2 or later
- print the selected flexcom mode after the hardware version

v1:
This series of patches a support to the Atmel Flexcom, a wrapper which
integrates an USART, a SPI controller and a TWI controller. Only one
peripheral can be used at a time. The active function is selected though
the Flexcom Mode Register.

Cyrille Pitchen (3):
  mfd: atmel-flexcom: create include file with macros used by DT
bindings
  mfd: devicetree: add bindings for Atmel Flexcom
  mfd: atmel-flexcom: add a driver for Atmel Flexible Serial
Communication Unit

 .../devicetree/bindings/mfd/atmel-flexcom.txt  |  67 +
 drivers/mfd/Kconfig|  11 +++
 drivers/mfd/Makefile   |   1 +
 drivers/mfd/atmel-flexcom.c| 104 +
 include/dt-bindings/mfd/atmel-flexcom.h|  16 
 5 files changed, 199 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
 create mode 100644 drivers/mfd/atmel-flexcom.c
 create mode 100644 include/dt-bindings/mfd/atmel-flexcom.h

-- 
1.8.2.2

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


Re: [PATCH linux-next v5 1/5] mtd: spi-nor: notify (Q)SPI controller about protocol change

2015-08-27 Thread Cyrille Pitchen
Hi Jonas,

Le 26/08/2015 16:02, Jonas Gorski a écrit :
 On Wed, Aug 26, 2015 at 2:30 PM, Cyrille Pitchen
 cyrille.pitc...@atmel.com wrote:
 Once the Quad SPI mode has been enabled on a Micron flash memory, this
 device expects ALL the following commands to use the SPI 4-4-4 protocol.
 The (Q)SPI controller needs to be notified about the protocol change so it
 can adapt and keep on dialoging with the Micron memory.
 
 Doesn't that mean you need to disable quad mode on removal? Else the
 following will break/fail:
 
 insmod atmel-quadspi.ko ~ spi-nor attaches - sees micron - enables quad 
 mode
 rmmod atmel-quadspi.ko ~ spi-nor detaches
 insmod atmel-quadspi.ko ~ spi-nor attaches - fails to read the id
 because flash is still in quad mode.


Indeed you're right such an issue does exist. So as you said one solution
could be create a new function to clean what have been done by spi_nor_scan()
then call it from remove() function of each driver calling spi_nor_scan() from
its probe().
However we could also enhance the probing of the memory. It is true that Micron
spi nor memories only accept SPI 4-4-4 commands once switched in quad mode but
actually they also provide a new command for this purpose:
Multiple I/O Read ID (0xAF).
Hence we could first try to probe using the regular Read ID (0x9F) command then
change the protocol, for instance to SPI 4-4-4, and try the 0xAF command.
I don't think all combinations for command/protocol need to be tested: for
Micron memories, their datasheets claim the 0x9F command is only supported in
extended spi mode so for the SPI 1-1-1 protocol whereas the 0xAF command
only works in dual or quad modes.
On the other hand Spansion memories still reply to the regular 0x9F command in
SPI 1-1-1 protocol even after their quad mode had been enabled.
For other manufacturers, well... I don't know!

Some of the advantages of the probe solution as compared to the remove one are:
- we don't need to patch all drivers using spi_nor_scan() to call a new
  function from their remove().
- it doesn't rely on the assumption that the spi-nor memory starts in
  SPI 1-1-1 protocol. As a matter of fact the remove() won't be called for
  built-in modules or in many (all ?) cases of reset. Moreover some bootloaders
  may have already enabled the quad mode before starting the Linux kernel. This
  is what the sama5d2 romcode does when it is configured to boot from a QSPI
  memory.

Anyway you're right and the issue need to be addressed but maybe in another
dedicated patch ?
 
 Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
 Acked-by: Marek Vasut ma...@denx.de
 Acked-by: Bean Huo bean...@micron.com
 ---
  drivers/mtd/spi-nor/spi-nor.c | 21 +
  include/linux/mtd/spi-nor.h   | 13 +
  2 files changed, 34 insertions(+)

 diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
 index c27d427fead4..c8810313a752 100644
 --- a/drivers/mtd/spi-nor/spi-nor.c
 +++ b/drivers/mtd/spi-nor/spi-nor.c
 @@ -165,6 +165,22 @@ static inline int write_disable(struct spi_nor *nor)
 return nor-write_reg(nor, SPINOR_OP_WRDI, NULL, 0, 0);
  }

 +/*
 + * Let the spi-nor framework notify lower layers, especially the driver of 
 the
 + * (Q)SPI controller, about the new protocol to be used. Indeed, once the
 + * spi-nor framework has sent manufacturer specific commands to a memory to
 + * enable its Quad SPI mode, it should immediately after tell the QSPI
 + * controller to use the very same Quad SPI protocol as expected by the 
 memory.
 + */
 +static inline int spi_nor_set_protocol(struct spi_nor *nor,
 +  enum spi_protocol proto)
 +{
 +   if (nor-set_protocol)
 +   return nor-set_protocol(nor, proto);
 +
 +   return 0;
 
 Shouldn't the default assumption be that it won't support it? Also it
 might make sense to first check if it's supported before enabling it
 in the chip, so that we don't enable something just to then find out
 we can't back out of it.
 
 I also wonder if we need an extra flag for that as at least SPI has
 RX_{DUAL,QUAD} and TX_{DUAL,QUAD} separated, so in theory there could
 be a controller that supports quad read, but not quad write, so we
 shouldn't be using the quad mode in that case. m25p80 currently sets
 SPI_NOR_{DUAL,QUAD} only based on SPI_RX_{DUAL,QUAD}, so that would
 then fail.
 
 At least the n25q32 seems to support the boring 1_1_2 and 1_1_4
 commands, so these should work in case the spi controller does not
 support quad tx, but quad rx.
 
 So maybe an additional flag for the full dual/quad modes would be in order.
 

My first thought was to return -ENOSYS when the set_protocol() callback is not
implemented but logically none of the already existing drivers implements it.
So I made this new callback optional. This way, micron_quad_enable() works the
exact same way as before for all the existing drivers so no regression or side-
effect should be introduced by this patch.

Besides

[PATCH linux-next v5 2/5] Documentation: mtd: add a DT property to set the number of dummy cycles

2015-08-26 Thread Cyrille Pitchen
Depending on the SPI clock frequency, the Fast Read op code and the
Single/Dual Data Rate mode, the number of dummy cycles can be tuned to
improve transfer speed.
The actual number of dummy cycles is specific for each memory model and is
provided by the manufacturer thanks to the memory datasheet.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt 
b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
index 2bee68103b01..4387567d8024 100644
--- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
+++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
@@ -19,6 +19,11 @@ Optional properties:
all chips and support for it can not be detected at runtime.
Refer to your chips' datasheet to check if this is supported
by your chip.
+- m25p,num-dummy-cycles : Set the number of dummy cycles for Fast Read 
commands.
+  Depending on the manufacturer additional dedicated
+  commands are sent to the flash memory so the
+  controller and the memory can agree on the number of
+  dummy cycles to use.
 
 Example:
 
@@ -29,4 +34,5 @@ Example:
reg = 0;
spi-max-frequency = 4000;
m25p,fast-read;
+   m25p,num-dummy-cycles = 8;
};
-- 
1.8.2.2

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


[PATCH linux-next v5 5/5] mtd: atmel-quadspi: add driver for Atmel QSPI controller

2015-08-26 Thread Cyrille Pitchen
This driver add support to the new Atmel QSPI controller embedded into
sama5d2x SoCs. It expects a NOR memory to be connected to the QSPI
controller.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
Acked-by: Nicolas Ferre nicolas.fe...@atmel.com
---
 drivers/mtd/spi-nor/Kconfig |   7 +
 drivers/mtd/spi-nor/Makefile|   1 +
 drivers/mtd/spi-nor/atmel-quadspi.c | 859 
 3 files changed, 867 insertions(+)
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 89bf4c1faa2b..7a3d55429550 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -29,6 +29,13 @@ config SPI_FSL_QUADSPI
  This controller does not support generic SPI. It only supports
  SPI NOR.
 
+config SPI_ATMEL_QUADSPI
+   tristate Atmel Quad SPI Controller
+   depends on OF  HAS_DMA  (ARCH_AT91 || COMPILE_TEST)
+   help
+ This enables support for the Quad SPI controller in master mode.
+ We only connect the NOR to this controller now.
+
 config SPI_NXP_SPIFI
tristate NXP SPI Flash Interface (SPIFI)
depends on OF  (ARCH_LPC18XX || COMPILE_TEST)
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index e5ef8582..f5d23d7379bb 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_MTD_SPI_NOR)  += spi-nor.o
 obj-$(CONFIG_SPI_FSL_QUADSPI)  += fsl-quadspi.o
+obj-$(CONFIG_SPI_ATMEL_QUADSPI)+= atmel-quadspi.o
 obj-$(CONFIG_SPI_NXP_SPIFI)+= nxp-spifi.o
diff --git a/drivers/mtd/spi-nor/atmel-quadspi.c 
b/drivers/mtd/spi-nor/atmel-quadspi.c
new file mode 100644
index ..003cdf00e8b1
--- /dev/null
+++ b/drivers/mtd/spi-nor/atmel-quadspi.c
@@ -0,0 +1,859 @@
+/*
+ * Driver for Atmel QSPI Controller
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen cyrille.pitc...@atmel.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see http://www.gnu.org/licenses/.
+ *
+ * This driver is based on drivers/mtd/spi-nor/fsl-quadspi.c from Freescale.
+ */
+
+#include linux/kernel.h
+#include linux/clk.h
+#include linux/module.h
+#include linux/platform_device.h
+#include linux/delay.h
+#include linux/dma-mapping.h
+#include linux/dmaengine.h
+#include linux/err.h
+#include linux/interrupt.h
+#include linux/mtd/mtd.h
+#include linux/mtd/partitions.h
+#include linux/mtd/spi-nor.h
+#include linux/platform_data/atmel.h
+#include linux/platform_data/dma-atmel.h
+#include linux/of.h
+
+#include linux/io.h
+#include linux/gpio.h
+#include linux/pinctrl/consumer.h
+
+/* QSPI register offsets */
+#define QSPI_CR  0x  /* Control Register */
+#define QSPI_MR  0x0004  /* Mode Register */
+#define QSPI_RD  0x0008  /* Receive Data Register */
+#define QSPI_TD  0x000c  /* Transmit Data Register */
+#define QSPI_SR  0x0010  /* Status Register */
+#define QSPI_IER 0x0014  /* Interrupt Enable Register */
+#define QSPI_IDR 0x0018  /* Interrupt Disable Register */
+#define QSPI_IMR 0x001c  /* Interrupt Mask Register */
+#define QSPI_SCR 0x0020  /* Serial Clock Register */
+
+#define QSPI_IAR 0x0030  /* Instruction Address Register */
+#define QSPI_ICR 0x0034  /* Instruction Code Register */
+#define QSPI_IFR 0x0038  /* Instruction Frame Register */
+
+#define QSPI_SMR 0x0040  /* Scrambling Mode Register */
+#define QSPI_SKR 0x0044  /* Scrambling Key Register */
+
+#define QSPI_WPMR0x00E4  /* Write Protection Mode Register */
+#define QSPI_WPSR0x00E8  /* Write Protection Status Register */
+
+#define QSPI_VERSION 0x00FC  /* Version Register */
+
+
+/* Bitfields in QSPI_CR (Control Register) */
+#define QSPI_CR_QSPIEN  BIT(0)
+#define QSPI_CR_QSPIDIS BIT(1)
+#define QSPI_CR_SWRST   BIT(7)
+#define QSPI_CR_LASTXFERBIT(24)
+
+/* Bitfields in QSPI_MR (Mode Register) */
+#define QSPI_MR_SSM BIT(0)
+#define QSPI_MR_LLB BIT(1)
+#define QSPI_MR_WDRBT   BIT(2)
+#define QSPI_MR_SMRMBIT(3)
+#define QSPI_MR_CSMODE_MASK GENMASK(5, 4)
+#define QSPI_MR_CSMODE_NOT_RELOADED (0  4)
+#define QSPI_MR_CSMODE_LASTXFER (1  4)
+#define QSPI_MR_CSMODE_SYSTEMATICALLY   (2  4)
+#define QSPI_MR_NBBITS_MASK GENMASK(11, 8)
+#define

[PATCH linux-next v5 3/5] mtd: spi-nor: allow to tune the number of dummy cycles

2015-08-26 Thread Cyrille Pitchen
The number of dummy cycles used during Fast Read commands can be reduced
to improve transfer performances. Each manufacturer has a dedicated set of
registers to provide the memory with the exact number of dummy cycles it
should expect. Both the memory and the (Q)SPI controller must agree on
this number of dummy cycles.

The number of dummy cycles can be found into the memory datasheet and
mostly depends on the SPI clock frequency, the Fast Read op code and the
Single/Dual Data Rate mode.

Probing JEDEC Serial Flash Discoverable Parameters (SFDP) tables would
only provide the driver with a high enough number of dummy cycles for each
Fast Read command to be used for all clock frequencies: this solution
would not be optimized.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 drivers/mtd/spi-nor/spi-nor.c | 102 ++
 include/linux/mtd/spi-nor.h   |   2 +
 2 files changed, 85 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index c8810313a752..46d6e02f7560 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -121,24 +121,6 @@ static int read_cr(struct spi_nor *nor)
 }
 
 /*
- * Dummy Cycle calculation for different type of read.
- * It can be used to support more commands with
- * different dummy cycle requirements.
- */
-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
-{
-   switch (nor-flash_read) {
-   case SPI_NOR_FAST:
-   case SPI_NOR_DUAL:
-   case SPI_NOR_QUAD:
-   return 8;
-   case SPI_NOR_NORMAL:
-   return 0;
-   }
-   return 0;
-}
-
-/*
  * Write status register 1 byte
  * Returns negative if error occurred.
  */
@@ -1008,6 +990,86 @@ static int set_quad_mode(struct spi_nor *nor, const 
struct flash_info *info)
}
 }
 
+static int micron_set_dummy_cycles(struct spi_nor *nor)
+{
+   int ret;
+   u8 val, mask;
+
+   /* Read the Volatile Configuration Register (VCR). */
+   ret = nor-read_reg(nor, SPINOR_OP_RD_VCR, val, 1);
+   if (ret  0) {
+   dev_err(nor-dev, error %d reading VCR\n, ret);
+   return ret;
+   }
+
+   write_enable(nor);
+
+   /* Update the number of dummy into the VCR. */
+   mask = GENMASK(7, 4);
+   val = ~mask;
+   val |= (nor-read_dummy  4)  mask;
+   ret = nor-write_reg(nor, SPINOR_OP_WR_VCR, val, 1, 0);
+   if (ret  0) {
+   dev_err(nor-dev, error while writing VCR register\n);
+   return ret;
+   }
+
+   ret = spi_nor_wait_till_ready(nor);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
+/*
+ * Dummy Cycle calculation for different type of read.
+ * It can be used to support more commands with
+ * different dummy cycle requirements.
+ */
+static int spi_nor_read_dummy_cycles(struct spi_nor *nor,
+const struct flash_info *info)
+{
+   struct device_node *np = nor-dev-of_node;
+   struct device *dev = nor-dev;
+   u32 num_dummy_cycles;
+
+   if (np  !of_property_read_u32(np, m25p,num-dummy-cycles,
+   num_dummy_cycles)) {
+   nor-read_dummy = num_dummy_cycles;
+
+   /*
+* This switch block might be moved at the end of the function,
+* once nor-read_dummy has been set, but it was not tested with
+* all Micron memories.
+* Now the m25p,num-dummy-cycles property needs to be
+* explicitly set in the device tree so the switch statement is
+* executed. This should avoid unwanted side effects and keep
+* backward compatibility.
+*/
+   switch (JEDEC_MFR(info)) {
+   case CFI_MFR_ST:
+   return micron_set_dummy_cycles(nor);
+   default:
+   dev_warn(dev,
+Tuning of the number of dummy cycles is not 
implemented for spi-nor of this manufacturer,\n
+ignoring the DT property value and falling 
back to the framework default settings.\n);
+   break;
+   }
+   }
+
+   /* Fallback to legacy code. */
+   switch (nor-flash_read) {
+   case SPI_NOR_FAST:
+   case SPI_NOR_DUAL:
+   case SPI_NOR_QUAD:
+   nor-read_dummy = 8;
+   case SPI_NOR_NORMAL:
+   nor-read_dummy = 0;
+   }
+
+   return 0;
+}
+
 static int spi_nor_check(struct spi_nor *nor)
 {
if (!nor-dev || !nor-read || !nor-write ||
@@ -1208,7 +1270,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
nor-addr_width = 3;
}
 
-   nor-read_dummy = spi_nor_read_dummy_cycles(nor);
+   ret = spi_nor_read_dummy_cycles(nor, info);
+   if (ret)
+   return ret

[PATCH linux-next v5 4/5] Documentation: atmel-quadspi: add binding file for Atmel QSPI driver

2015-08-26 Thread Cyrille Pitchen
This patch documents the DT bindings for the driver of the Atmel QSPI
controller embedded inside sama5d2x SoCs.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
Acked-by: Nicolas Ferre nicolas.fe...@atmel.com
Acked-by: Marek Vasut ma...@denx.de
---
 .../devicetree/bindings/mtd/atmel-quadspi.txt  | 29 ++
 1 file changed, 29 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt

diff --git a/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt 
b/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
new file mode 100644
index ..0b8d545bb198
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
@@ -0,0 +1,29 @@
+* Atmel Quad Serial Peripheral Interface (QSPI)
+
+Required properties:
+- compatible: should be atmel,sama5d2-qspi
+- reg:the first contains the register location and length,
+  the second contains the memory mapping address and length
+- interrupts: should contain the interrupt for the device
+- clocks: the phandle of the clock needed by the QSPI controller
+- #address-cells: should be 1
+- #size-cells:should be 0
+
+Example:
+
+spi@f002 {
+   compatible = atmel,sama5d2-qspi;
+   reg = 0xf002 0x100,
+ 0xd000 0x800;
+   interrupts = 52 IRQ_TYPE_LEVEL_HIGH 7;
+   clocks = spi0_clk;
+   #address-cells = 1;
+   #size-cells = 0;
+   pinctrl-names = default;
+   pinctrl-0 = pinctrl_spi0_default;
+   status = okay;
+
+   m25p80@0 {
+   ...
+   };
+};
-- 
1.8.2.2

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


[PATCH linux-next v5 0/5] add driver for Atmel QSPI controller

2015-08-26 Thread Cyrille Pitchen
ChangeLog

v5:
- remove unused inline functions qspi_read[bw]() and qspi_write[bw](),
  keep only qspi_readl() and qspi_writel().
- use reinit_completion() instead of init_completion() during run time,
  call init_completion() once for all in the probe().
- add a dev_warn() when trying to tune the number of dummy cycles for
  spi-nor of a not supported manufacturer then fall back to the default
  framework value.
- reword some comments.
- add Acked-by: Marek Vasut ma...@denx.de for patches 1 and 4.
- add Acked-by: Bean Huo bean...@micron.com for patch 1.

v4:
- add OF  HAS_DMA dependency in Kconfig for Atmel Quad SPI driver.
- return -ENOMEM instead of the return code of dma_mapping_error() as this
  function returns a boolean on ARM achitecture.
- add Acked-by: Nicolas Ferre nicolas.fe...@atmel.com for Atmel Quad
  SPI driver and its DT binding documentation.

v3:
- reword the comment which explains that spi_nor_set_protocol() is used by
  the spi-nor framework to notify lower layers, especially the (Q)SPI
  controller about a protocol change.
- change the definitions of register/bitfield macros in the Atmel QSPI
  controller driver: get rid of concatenation operator and use BIT and
  GENMASK macros when possible.
- use #define[SPACE] instead of #define[TAB]

v2:
- remove the patches to set the latency code of Spansion QSPI memories
  (support of Spansion memories may be submitted in later series).
- rename qspi node into spi in the DT example to fit ePAPR standard.
- remove the useless qspi0 label from the DT node example.
- remove the leading 0 from the size of the second memory region to make
  it consistent with the size of the first memory region.
- indent the DT bindings documentation to make it more readable.
- remove the useless .bus  = platform_bus_type, line from the
  platform driver definition.

v1:

This series of patches add support for the new Atmel QSPI controller
embedded inside sama5d2x SoCs.

These patches were first developped for linux-3.18-at91 and tested on a
sama5d27 Xplained ultra board, which embeds a Micron n25q128a13 QSPI NOR
flash memory. Then the series was adapted for mainline.

Cyrille Pitchen (5):
  mtd: spi-nor: notify (Q)SPI controller about protocol change
  Documentation: mtd: add a DT property to set the number of dummy
cycles
  mtd: spi-nor: allow to tune the number of dummy cycles
  Documentation: atmel-quadspi: add binding file for Atmel QSPI driver
  mtd: atmel-quadspi: add driver for Atmel QSPI controller

 .../devicetree/bindings/mtd/atmel-quadspi.txt  |  29 +
 .../devicetree/bindings/mtd/jedec,spi-nor.txt  |   6 +
 drivers/mtd/spi-nor/Kconfig|   7 +
 drivers/mtd/spi-nor/Makefile   |   1 +
 drivers/mtd/spi-nor/atmel-quadspi.c| 859 +
 drivers/mtd/spi-nor/spi-nor.c  | 123 ++-
 include/linux/mtd/spi-nor.h|  15 +
 7 files changed, 1021 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

-- 
1.8.2.2

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


[PATCH linux-next v5 1/5] mtd: spi-nor: notify (Q)SPI controller about protocol change

2015-08-26 Thread Cyrille Pitchen
Once the Quad SPI mode has been enabled on a Micron flash memory, this
device expects ALL the following commands to use the SPI 4-4-4 protocol.
The (Q)SPI controller needs to be notified about the protocol change so it
can adapt and keep on dialoging with the Micron memory.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
Acked-by: Marek Vasut ma...@denx.de
Acked-by: Bean Huo bean...@micron.com
---
 drivers/mtd/spi-nor/spi-nor.c | 21 +
 include/linux/mtd/spi-nor.h   | 13 +
 2 files changed, 34 insertions(+)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index c27d427fead4..c8810313a752 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -165,6 +165,22 @@ static inline int write_disable(struct spi_nor *nor)
return nor-write_reg(nor, SPINOR_OP_WRDI, NULL, 0, 0);
 }
 
+/*
+ * Let the spi-nor framework notify lower layers, especially the driver of the
+ * (Q)SPI controller, about the new protocol to be used. Indeed, once the
+ * spi-nor framework has sent manufacturer specific commands to a memory to
+ * enable its Quad SPI mode, it should immediately after tell the QSPI
+ * controller to use the very same Quad SPI protocol as expected by the memory.
+ */
+static inline int spi_nor_set_protocol(struct spi_nor *nor,
+  enum spi_protocol proto)
+{
+   if (nor-set_protocol)
+   return nor-set_protocol(nor, proto);
+
+   return 0;
+}
+
 static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
 {
return mtd-priv;
@@ -940,6 +956,11 @@ static int micron_quad_enable(struct spi_nor *nor)
return ret;
}
 
+   /* switch protocol to Quad CMD 4-4-4 */
+   ret = spi_nor_set_protocol(nor, SPI_PROTO_4_4_4);
+   if (ret)
+   return ret;
+
ret = spi_nor_wait_till_ready(nor);
if (ret)
return ret;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index e5409524bb0a..1bf6f11310ef 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -87,6 +87,16 @@ enum read_mode {
SPI_NOR_QUAD,
 };
 
+enum spi_protocol {
+   SPI_PROTO_1_1_1,/* SPI */
+   SPI_PROTO_1_1_2,/* Dual Output */
+   SPI_PROTO_1_1_4,/* Quad Output */
+   SPI_PROTO_1_2_2,/* Dual IO */
+   SPI_PROTO_1_4_4,/* Quad IO */
+   SPI_PROTO_2_2_2,/* Dual Command */
+   SPI_PROTO_4_4_4,/* Quad Command */
+};
+
 /**
  * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer
  * @wren:  command for Write Enable, or 0x00 for not required
@@ -149,6 +159,7 @@ enum spi_nor_option_flags {
  * read/write/erase/lock/unlock operations
  * @read_xfer: [OPTIONAL] the read fundamental primitive
  * @write_xfer:[OPTIONAL] the writefundamental primitive
+ * @set_protocol:  [OPTIONAL] notify about protocol change
  * @read_reg:  [DRIVER-SPECIFIC] read out the register
  * @write_reg: [DRIVER-SPECIFIC] write data to the register
  * @read:  [DRIVER-SPECIFIC] read data from the SPI NOR
@@ -185,6 +196,8 @@ struct spi_nor {
int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len,
int write_enable);
 
+   int (*set_protocol)(struct spi_nor *nor, enum spi_protocol proto);
+
int (*read)(struct spi_nor *nor, loff_t from,
size_t len, size_t *retlen, u_char *read_buf);
void (*write)(struct spi_nor *nor, loff_t to,
-- 
1.8.2.2

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


Re: [PATCH linux-next v4 5/5] mtd: atmel-quadspi: add driver for Atmel QSPI controller

2015-08-25 Thread Cyrille Pitchen
Le 25/08/2015 11:46, Jonas Gorski a écrit :
 On Mon, Aug 24, 2015 at 7:45 PM, Marek Vasut ma...@denx.de wrote:
 On Monday, August 24, 2015 at 07:04:38 PM, Cyrille Pitchen wrote:
 Hi Marek,

 Hi!

 Le 24/08/2015 13:03, Marek Vasut a écrit :
 On Monday, August 24, 2015 at 12:14:00 PM, Cyrille Pitchen wrote:
 This driver add support to the new Atmel QSPI controller embedded into
 sama5d2x SoCs. It expects a NOR memory to be connected to the QSPI
 controller.

 [...]

 +  /* Compute address parameters */
 +  switch (cmd-enable.bits.address) {
 +  case 4:
 +  ifr |= QSPI_IFR_ADDRL;
 +  /*break;*/ /* fallback to the 24bit address case */

 What's this commented out bit of code for ? :-)

 I just wanted to stress out there was no missing break;.
 I've reworded the comment to:
 /* No break on purpose: fallback to the 24bit address case. */

 Oh, the address is in bytes . I see, yes, it makes sense to be more
 explicit here about the purpose of the fallback. I think this change
 in the comment will make it easier for everyone who comes back in a
 few years and reads this code.
 
 I think you are looking for the term (switch case) fallthrough, not
 fallback. Fallback makes it sound like there is something missing,
 or an invalid state.
 
 
 Jonas
 

will be modified in the next series, thanks for the review!
--
To unsubscribe from this list: send the line unsubscribe devicetree in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH linux-next v4 5/5] mtd: atmel-quadspi: add driver for Atmel QSPI controller

2015-08-25 Thread Cyrille Pitchen
Hi Marek,

Le 24/08/2015 13:03, Marek Vasut a écrit :
 On Monday, August 24, 2015 at 12:14:00 PM, Cyrille Pitchen wrote:
 This driver add support to the new Atmel QSPI controller embedded into
 sama5d2x SoCs. It expects a NOR memory to be connected to the QSPI
 controller.

 Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
 Acked-by: Nicolas Ferre nicolas.fe...@atmel.com
 
 Hi,
 
 [...]
 
 +/* Register access macros */
 
 These are functions, not macros :)
 
 btw is there any reason for these ? I'd say, just put the read*() and
 write*() functions directly into the code and be done with it, it is
 much less confusing.

If you don't mind, I'd rather keep some of these inline functions. I have
no strong justification, it's more a personal taste: it makes lines
shorter as it avoids the need to add -regs + .
Also it makes the code consistent with other Atmel drivers which already
use such wrappers.

However I'll fix the comment and remove the byte and word versions, which
are not used. So only qspi_readl() and qspi_writel() are left.

Does it sound good to you?

 
 Also, why do you use the _relaxed() versions of the functions ?
 
 +static inline u32 qspi_readl(struct atmel_qspi *aq, u32 reg)
 +{
 +return readl_relaxed(aq-regs + reg);
 +}
 +
 +static inline void qspi_writel(struct atmel_qspi *aq, u32 reg, u32 value)
 +{
 +writel_relaxed(value, aq-regs + reg);
 +}
 +
 +static inline u16 qspi_readw(struct atmel_qspi *aq, u32 reg)
 +{
 +return readw_relaxed(aq-regs + reg);
 +}
 +
 +static inline void qspi_writew(struct atmel_qspi *aq, u32 reg, u16 value)
 +{
 +writew_relaxed(value, aq-regs + reg);
 +}
 +
 +static inline u8 qspi_readb(struct atmel_qspi *aq, u32 reg)
 +{
 +return readb_relaxed(aq-regs + reg);
 +}
 +
 +static inline void qspi_writeb(struct atmel_qspi *aq, u32 reg, u8 value)
 +{
 +writeb_relaxed(value, aq-regs + reg);
 +}
 
 [...]
 
 Hope this helps :)
 

Best regards,

Cyrille
--
To unsubscribe from this list: send the line unsubscribe devicetree in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v8 1/2] mfd: devicetree: add bindings for Atmel Flexcom

2015-08-25 Thread Cyrille Pitchen
Hi all,

any feedback on this kind of DT bindings?
Is it a proper way of using the ranges property?

Best regards,

Cyrille

Le 24/07/2015 17:08, Lee Jones a écrit :
 DT chaps,
 
 Please can you take a look at this binding.
 
 In particular the use of the 'ranges' property to store device 'mode'.
 
 This patch documents the DT bindings for the Atmel Flexcom which will be
 introduced by sama5d2x SoCs. These bindings will be used by the actual
 Flexcom driver to be sent in another patch.

 Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
 Acked-by: Nicolas Ferre nicolas.fe...@atmel.com
 ---
  .../devicetree/bindings/mfd/atmel-flexcom.txt  | 68 
 ++
  1 file changed, 68 insertions(+)
  create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt

 diff --git a/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt 
 b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
 new file mode 100644
 index ..588d527dbfa7
 --- /dev/null
 +++ b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
 @@ -0,0 +1,68 @@
 +* Device tree bindings for Atmel Flexcom (Flexible Serial Communication 
 Unit)
 +
 +The Atmel Flexcom is just a wrapper which embeds a SPI controller, an I2C
 +controller and an USART. Only one function can be used at a time and is 
 chosen
 +at boot time according to the device tree.
 +
 +Required properties:
 +- compatible:   Should be atmel,sama5d2-flexcom
 +- reg:  Should be the pair (offset, size) for the 
 Flexcom
 +dedicated I/O registers (without USART, TWI or SPI
 +registers).
 +- clocks:   Should be the Flexcom peripheral clock from PMC.
 +- #address-cells:   Should be 2
 +- #size-cells:  Should be 1
 +- ranges:   Should be a list of ranges.
 +One range per peripheral wrapped by the Flexcom. So each
 +range is a triplet (child_addr, parent_addr, size). The
 +first u32 of child_addr is the value to be set in the
 +Operating Mode bitfield of the Flexcom Mode Register.
 +Then parent_addr stores the base address of the
 +corresponding peripheral in the system memory. Finally,
 +size if the size of the memory region of this
 +peripheral.
 +
 +Required child:
 +A single available child for the serial controller to enable.
 +
 +Required properties of this child:
 +- reg:  Should be a pair (child_addr, size) with 
 child_addr
 +matching one of the parent ranges.
 +- clocks:   Should be the very same phandle as for the parent's one.
 +
 +Other properties remain unchanged. See documentation of the respective 
 device:
 +- ../serial/atmel-usart.txt
 +- ../spi/spi_atmel.txt
 +- ../i2c/i2c-at91.txt
 +
 +Example:
 +
 +flexcom@f8034000 {
 +compatible = atmel,sama5d2-flexcom;
 +reg = 0xf8034000 0x200;
 +clocks = flx0_clk;
 +#address-cells = 2;
 +#size-cells = 1;
 +ranges = 1 0 0xf8034200 0x200  /* opmode 1: USART */
 +  2 0 0xf8034400 0x200  /* opmode 2: SPI */
 +  3 0 0xf8034600 0x200;/* opmode 3: I2C */
 +
 +spi@2,0 {
 +compatible = atmel,at91rm9200-spi;
 +reg = 2 0 0x200;
 +interrupts = 19 IRQ_TYPE_LEVEL_HIGH 7;
 +pinctrl-names = default;
 +pinctrl-0 = pinctrl_flx0_default;
 +#address-cells = 1;
 +#size-cells = 0;
 +clocks = flx0_clk;
 +clock-names = spi_clk;
 +atmel,fifo-size = 32;
 +
 +mtd_dataflash@0 {
 +compatible = atmel,at25f512b;
 +reg = 0;
 +spi-max-frequency = 2000;
 +};
 +};
 +};
 

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


Re: [PATCH linux-next v4 5/5] mtd: atmel-quadspi: add driver for Atmel QSPI controller

2015-08-25 Thread Cyrille Pitchen
Hi!

Le 25/08/2015 03:44, Bean Huo 霍斌斌 (beanhuo) a écrit :
 
 +nor-read_reg = atmel_qspi_read_reg;
 +nor-write_reg = atmel_qspi_write_reg;
 +nor-read = atmel_qspi_read;
 +nor-write = atmel_qspi_write;
 +nor-erase = atmel_qspi_erase;
 +nor-set_protocol = atmel_qspi_set_protocol;
 
 This is very good, the structure of spi_nor should add a hook function to 
 notify spi controller 
 That spi nor transfer protocol already changed.
 
 +
 +if (of_modalias_node(child, modalias, sizeof(modalias))  0) {
 +err = -ENODEV;
 +goto release_channel;
 +}
 +
 +err = of_property_read_u32(child, spi-max-frequency, aq-clk_rate);
 +if (err  0)
 +goto release_channel;
 +
 +err = atmel_qspi_init(aq);
 +if (err)
 +goto release_channel;
 +
 +nor-dev-of_node = child;
 +err = spi_nor_scan(nor, modalias, SPI_NOR_QUAD);
  goto release_channel;
 +
 
 
 ...
 
 static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)  {
   return mtd-priv;
 @@ -944,6 +960,11 @@ static int micron_quad_enable(struct spi_nor *nor)
  return ret;
  }

 +/* switch protocol to Quad CMD 4-4-4 */
 +ret = spi_nor_set_protocol(nor, SPI_PROTO_4_4_4);
 +if (ret)
 +return ret;
 +
 
 This make sense,from spi nor side,once its protocol being changed,
 Mtd layer must notify this status to spi nor controller immediately,
 And spi nor controller also should re-adjust its protocol.
 Otherwise, following reading SR operation will fail. 
 

  ret = spi_nor_wait_till_ready(nor);
  if (ret)
  return ret;
 
 If my ack has any value in here, feel free to add it.
 
 Acked-by: Bean Huo bean...@micron.com
 

Since your comments deal with the protocol change, I'll add your ack to the
first patch of the series:
mtd: spi-nor: notify (Q)SPI controller about protocol change

Thanks for your review!

Best regards,

Cyrille

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


Re: [PATCH linux-next v4 3/5] mtd: spi-nor: allow to tune the number of dummy cycles

2015-08-24 Thread Cyrille Pitchen
Hi Marek,

Le 24/08/2015 12:48, Marek Vasut a écrit :
 On Monday, August 24, 2015 at 12:13:58 PM, Cyrille Pitchen wrote:
 The number of dummy cycles used during Fast Read commands can be reduced
 to improve transfer performances. Each manufacturer has a dedicated set of
 registers to provide the memory with the exact number of dummy cycles it
 should expect. Both the memory and the (Q)SPI controller must agree on
 this number of dummy cycles.

 The number of dummy cycles can be found into the memory datasheet and
 mostly depends on the SPI clock frequency, the Fast Read op code and the
 Single/Dual Data Rate mode.

 Probing JEDEC Serial Flash Discoverable Parameters (SFDP) tables would
 only provide the driver with a high enough number of dummy cycles for each
 Fast Read command to be used for all clock frequencies: this solution
 would not be optimized.

 Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
 
 Hi!
 
  drivers/mtd/spi-nor/spi-nor.c | 97
 ++- include/linux/mtd/spi-nor.h  
 |  2 +
  2 files changed, 80 insertions(+), 19 deletions(-)

 diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
 index e2a6029dc056..869e098a6841 100644
 --- a/drivers/mtd/spi-nor/spi-nor.c
 +++ b/drivers/mtd/spi-nor/spi-nor.c
 @@ -119,24 +119,6 @@ static int read_cr(struct spi_nor *nor)
  }

  /*
 - * Dummy Cycle calculation for different type of read.
 - * It can be used to support more commands with
 - * different dummy cycle requirements.
 - */
 -static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
 -{
 -switch (nor-flash_read) {
 -case SPI_NOR_FAST:
 -case SPI_NOR_DUAL:
 -case SPI_NOR_QUAD:
 -return 8;
 -case SPI_NOR_NORMAL:
 -return 0;
 -}
 -return 0;
 -}
 
 You can probably just soup up this function so that it sets the
 nor-read_dummy, no ?


Actually, this is what the patch does: spi_nor_read_dummy_cycles() was reused
and enhanced few lines below where you've pointed out the 
switch (nor-flash_read) block should be move after the else block.

I think when I wrote the code I've chosen to move the definition of this
function instead of adding forward declarations of functions such as read_cr()
or write_sr_cr(), which are now called by micron_set_dummy_cycles().

 -/*
   * Write status register 1 byte
   * Returns negative if error occurred.
   */
 @@ -1012,6 +994,81 @@ static int set_quad_mode(struct spi_nor *nor, struct
 flash_info *info) }
  }

 +static int micron_set_dummy_cycles(struct spi_nor *nor)
 +{
 +int ret;
 +u8 val, mask;
 +
 +/* read the Volatile Configuration Register (VCR) */
 
 NIT: If this is a sentence, start it with capital letter and end it with 
 fullstop :)
 

done for the next version

 +ret = nor-read_reg(nor, SPINOR_OP_RD_VCR, val, 1);
 +if (ret  0) {
 +dev_err(nor-dev, error %d reading VCR\n, ret);
 +return ret;
 +}
 +
 +write_enable(nor);
 +
 +/* update the number of dummy into the VCR */
 
 DTTO
 

done for the next version

 +mask = GENMASK(7, 4);
 +val = ~mask;
 +val |= (nor-read_dummy  4)  mask;
 +ret = nor-write_reg(nor, SPINOR_OP_WR_VCR, val, 1, 0);
 +if (ret  0) {
 +dev_err(nor-dev, error while writing VCR register\n);
 +return ret;
 +}
 +
 +ret = spi_nor_wait_till_ready(nor);
 +if (ret)
 +return ret;
 +
 +return 0;
 +}
 +
 +/*
 + * Dummy Cycle calculation for different type of read.
 + * It can be used to support more commands with
 + * different dummy cycle requirements.
 + */
 +static int spi_nor_read_dummy_cycles(struct spi_nor *nor,
 + const struct flash_info *info)
 +{
 +struct device_node *np = nor-dev-of_node;
 +u32 num_dummy_cycles;
 +
 +if (np  !of_property_read_u32(np, m25p,num-dummy-cycles,
 +num_dummy_cycles)) {
 +nor-read_dummy = num_dummy_cycles;
 +
 +/*
 + * This switch block might be moved after the if...then...else
 + * statement but it was not tested with all Spansion or Micron
 + * memories.
 + * Now the m25p,num-dummy-cycles property needs to be
 + * explicitly set in the device tree so the switch statement is
 + * executed. This should avoid unwanted side effects and keep
 + * backward compatibility.
 + */
 +switch (JEDEC_MFR(info)) {
 +case CFI_MFR_ST:
 +return micron_set_dummy_cycles(nor);
 +default:
 
 If you do have m25p,num-dummy-cycles set for non-micron flash, you have a 
 problem here I believe.
 
 +break;
 +}
 +} else {
 
 The solution would be to drop this else {} bit here, so that if you fail in
 the DT-based configuration, you fall back to this old behavior. What do you 
 think please ? :)
 

Good idea!
I

Re: [PATCH linux-next v4 5/5] mtd: atmel-quadspi: add driver for Atmel QSPI controller

2015-08-24 Thread Cyrille Pitchen
Hi Marek,

Le 24/08/2015 13:03, Marek Vasut a écrit :
 On Monday, August 24, 2015 at 12:14:00 PM, Cyrille Pitchen wrote:
 This driver add support to the new Atmel QSPI controller embedded into
 sama5d2x SoCs. It expects a NOR memory to be connected to the QSPI
 controller.

 Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
 Acked-by: Nicolas Ferre nicolas.fe...@atmel.com
 
 Hi,
 
 [...]
 
 +/* Register access macros */
 
 These are functions, not macros :)
 
 btw is there any reason for these ? I'd say, just put the read*() and
 write*() functions directly into the code and be done with it, it is
 much less confusing.
 
 Also, why do you use the _relaxed() versions of the functions ?
 
 +static inline u32 qspi_readl(struct atmel_qspi *aq, u32 reg)
 +{
 +return readl_relaxed(aq-regs + reg);
 +}
 +
 +static inline void qspi_writel(struct atmel_qspi *aq, u32 reg, u32 value)
 +{
 +writel_relaxed(value, aq-regs + reg);
 +}
 +
 +static inline u16 qspi_readw(struct atmel_qspi *aq, u32 reg)
 +{
 +return readw_relaxed(aq-regs + reg);
 +}
 +
 +static inline void qspi_writew(struct atmel_qspi *aq, u32 reg, u16 value)
 +{
 +writew_relaxed(value, aq-regs + reg);
 +}
 +
 +static inline u8 qspi_readb(struct atmel_qspi *aq, u32 reg)
 +{
 +return readb_relaxed(aq-regs + reg);
 +}
 +
 +static inline void qspi_writeb(struct atmel_qspi *aq, u32 reg, u8 value)
 +{
 +writeb_relaxed(value, aq-regs + reg);
 +}
 
 [...]
 
 +static int atmel_qspi_run_command(struct atmel_qspi *aq,
 +  const struct atmel_qspi_command *cmd)
 +{
 +u32 iar, icr, ifr, sr;
 +int err = 0;
 +
 +iar = 0;
 +icr = 0;
 +ifr = aq-ifr_width | cmd-ifr_tfrtyp;
 +
 +/* Compute instruction parameters */
 +if (cmd-enable.bits.instruction) {
 +icr |= QSPI_ICR_INST(cmd-instruction);
 +ifr |= QSPI_IFR_INSTEN;
 +}
 +
 +/* Compute address parameters */
 +switch (cmd-enable.bits.address) {
 +case 4:
 +ifr |= QSPI_IFR_ADDRL;
 +/*break;*/ /* fallback to the 24bit address case */
 
 What's this commented out bit of code for ? :-)

I just wanted to stress out there was no missing break;.
I've reworded the comment to:
/* No break on purpose: fallback to the 24bit address case. */

 
 +case 3:
 +iar = (cmd-enable.bits.data) ? 0 : cmd-address;
 +ifr |= QSPI_IFR_ADDREN;
 +break;
 +case 0:
 +break;
 +default:
 +return -EINVAL;
 +}
 
 [...]
 
 +no_data:
 +/* Poll INSTRuction End status */
 +sr = qspi_readl(aq, QSPI_SR);
 +if (sr  QSPI_SR_INSTRE)
 +return err;
 +
 +/* Wait for INSTRuction End interrupt */
 +init_completion(aq-completion);
 
 You should use reinit_completion() in the code. init_completion()
 should be used only in the probe() function and nowhere else.

Alright. In the next version I'll rename the completion member of
struct atmel_qspi into cmd_completion. Also I'll add another dma_completion
member in this very same structure to replace the local
struct completion completion in atmel_qspi_run_dma_transfer().

Then I'll call init_completion() on both cmd_completion and dma_completion only
from atmel_qspi_probe() and reinit_completion() elsewhere.

 
 +aq-pending = 0;
 +qspi_writel(aq, QSPI_IER, QSPI_SR_INSTRE);
 +if (!wait_for_completion_timeout(aq-completion,
 + msecs_to_jiffies(1000)))
 +err = -ETIMEDOUT;
 +qspi_writel(aq, QSPI_IDR, QSPI_SR_INSTRE);
 +
 +return err;
 +}
 
 [...]
 
 Hope this helps :)
 

Indeed, it does! I still work on the next version of this series to take all 
your
comments into account.

Best regards,

Cyrille
--
To unsubscribe from this list: send the line unsubscribe devicetree in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH linux-next v4 3/5] mtd: spi-nor: allow to tune the number of dummy cycles

2015-08-24 Thread Cyrille Pitchen
The number of dummy cycles used during Fast Read commands can be reduced
to improve transfer performances. Each manufacturer has a dedicated set of
registers to provide the memory with the exact number of dummy cycles it
should expect. Both the memory and the (Q)SPI controller must agree on
this number of dummy cycles.

The number of dummy cycles can be found into the memory datasheet and
mostly depends on the SPI clock frequency, the Fast Read op code and the
Single/Dual Data Rate mode.

Probing JEDEC Serial Flash Discoverable Parameters (SFDP) tables would
only provide the driver with a high enough number of dummy cycles for each
Fast Read command to be used for all clock frequencies: this solution
would not be optimized.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 drivers/mtd/spi-nor/spi-nor.c | 97 ++-
 include/linux/mtd/spi-nor.h   |  2 +
 2 files changed, 80 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index e2a6029dc056..869e098a6841 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -119,24 +119,6 @@ static int read_cr(struct spi_nor *nor)
 }
 
 /*
- * Dummy Cycle calculation for different type of read.
- * It can be used to support more commands with
- * different dummy cycle requirements.
- */
-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
-{
-   switch (nor-flash_read) {
-   case SPI_NOR_FAST:
-   case SPI_NOR_DUAL:
-   case SPI_NOR_QUAD:
-   return 8;
-   case SPI_NOR_NORMAL:
-   return 0;
-   }
-   return 0;
-}
-
-/*
  * Write status register 1 byte
  * Returns negative if error occurred.
  */
@@ -1012,6 +994,81 @@ static int set_quad_mode(struct spi_nor *nor, struct 
flash_info *info)
}
 }
 
+static int micron_set_dummy_cycles(struct spi_nor *nor)
+{
+   int ret;
+   u8 val, mask;
+
+   /* read the Volatile Configuration Register (VCR) */
+   ret = nor-read_reg(nor, SPINOR_OP_RD_VCR, val, 1);
+   if (ret  0) {
+   dev_err(nor-dev, error %d reading VCR\n, ret);
+   return ret;
+   }
+
+   write_enable(nor);
+
+   /* update the number of dummy into the VCR */
+   mask = GENMASK(7, 4);
+   val = ~mask;
+   val |= (nor-read_dummy  4)  mask;
+   ret = nor-write_reg(nor, SPINOR_OP_WR_VCR, val, 1, 0);
+   if (ret  0) {
+   dev_err(nor-dev, error while writing VCR register\n);
+   return ret;
+   }
+
+   ret = spi_nor_wait_till_ready(nor);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
+/*
+ * Dummy Cycle calculation for different type of read.
+ * It can be used to support more commands with
+ * different dummy cycle requirements.
+ */
+static int spi_nor_read_dummy_cycles(struct spi_nor *nor,
+const struct flash_info *info)
+{
+   struct device_node *np = nor-dev-of_node;
+   u32 num_dummy_cycles;
+
+   if (np  !of_property_read_u32(np, m25p,num-dummy-cycles,
+   num_dummy_cycles)) {
+   nor-read_dummy = num_dummy_cycles;
+
+   /*
+* This switch block might be moved after the if...then...else
+* statement but it was not tested with all Spansion or Micron
+* memories.
+* Now the m25p,num-dummy-cycles property needs to be
+* explicitly set in the device tree so the switch statement is
+* executed. This should avoid unwanted side effects and keep
+* backward compatibility.
+*/
+   switch (JEDEC_MFR(info)) {
+   case CFI_MFR_ST:
+   return micron_set_dummy_cycles(nor);
+   default:
+   break;
+   }
+   } else {
+   switch (nor-flash_read) {
+   case SPI_NOR_FAST:
+   case SPI_NOR_DUAL:
+   case SPI_NOR_QUAD:
+   nor-read_dummy = 8;
+   case SPI_NOR_NORMAL:
+   nor-read_dummy = 0;
+   }
+   }
+
+   return 0;
+}
+
 static int spi_nor_check(struct spi_nor *nor)
 {
if (!nor-dev || !nor-read || !nor-write ||
@@ -1216,7 +1273,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
nor-addr_width = 3;
}
 
-   nor-read_dummy = spi_nor_read_dummy_cycles(nor);
+   ret = spi_nor_read_dummy_cycles(nor, info);
+   if (ret)
+   return ret;
 
dev_info(dev, %s (%lld Kbytes)\n, id-name,
(long long)mtd-size  10);
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 1bf6f11310ef..e03a4c4053d3 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -59,6 +59,8

[PATCH linux-next v4 1/5] mtd: spi-nor: notify (Q)SPI controller about protocol change

2015-08-24 Thread Cyrille Pitchen
Once the Quad SPI mode has been enabled on a Micron flash memory, this
device expects ALL the following commands to use the SPI 4-4-4 protocol.
The (Q)SPI controller needs to be notified about the protocol change so it
can adapt and keep on dialoging with the Micron memory.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 drivers/mtd/spi-nor/spi-nor.c | 21 +
 include/linux/mtd/spi-nor.h   | 13 +
 2 files changed, 34 insertions(+)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 47df4b5eae2f..e2a6029dc056 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -163,6 +163,22 @@ static inline int write_disable(struct spi_nor *nor)
return nor-write_reg(nor, SPINOR_OP_WRDI, NULL, 0, 0);
 }
 
+/*
+ * Let the spi-nor framework notify lower layers, especially the driver of the
+ * (Q)SPI controller, about the new protocol to be used. Indeed, once the
+ * spi-nor framework has sent manufacturer specific commands to a memory to
+ * enable its Quad SPI mode, it should immediately after tell the QSPI
+ * controller to use the very same Quad SPI protocol as expected by the memory.
+ */
+static inline int spi_nor_set_protocol(struct spi_nor *nor,
+  enum spi_protocol proto)
+{
+   if (nor-set_protocol)
+   return nor-set_protocol(nor, proto);
+
+   return 0;
+}
+
 static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
 {
return mtd-priv;
@@ -944,6 +960,11 @@ static int micron_quad_enable(struct spi_nor *nor)
return ret;
}
 
+   /* switch protocol to Quad CMD 4-4-4 */
+   ret = spi_nor_set_protocol(nor, SPI_PROTO_4_4_4);
+   if (ret)
+   return ret;
+
ret = spi_nor_wait_till_ready(nor);
if (ret)
return ret;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index e5409524bb0a..1bf6f11310ef 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -87,6 +87,16 @@ enum read_mode {
SPI_NOR_QUAD,
 };
 
+enum spi_protocol {
+   SPI_PROTO_1_1_1,/* SPI */
+   SPI_PROTO_1_1_2,/* Dual Output */
+   SPI_PROTO_1_1_4,/* Quad Output */
+   SPI_PROTO_1_2_2,/* Dual IO */
+   SPI_PROTO_1_4_4,/* Quad IO */
+   SPI_PROTO_2_2_2,/* Dual Command */
+   SPI_PROTO_4_4_4,/* Quad Command */
+};
+
 /**
  * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer
  * @wren:  command for Write Enable, or 0x00 for not required
@@ -149,6 +159,7 @@ enum spi_nor_option_flags {
  * read/write/erase/lock/unlock operations
  * @read_xfer: [OPTIONAL] the read fundamental primitive
  * @write_xfer:[OPTIONAL] the writefundamental primitive
+ * @set_protocol:  [OPTIONAL] notify about protocol change
  * @read_reg:  [DRIVER-SPECIFIC] read out the register
  * @write_reg: [DRIVER-SPECIFIC] write data to the register
  * @read:  [DRIVER-SPECIFIC] read data from the SPI NOR
@@ -185,6 +196,8 @@ struct spi_nor {
int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len,
int write_enable);
 
+   int (*set_protocol)(struct spi_nor *nor, enum spi_protocol proto);
+
int (*read)(struct spi_nor *nor, loff_t from,
size_t len, size_t *retlen, u_char *read_buf);
void (*write)(struct spi_nor *nor, loff_t to,
-- 
1.8.2.2

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


[PATCH linux-next v4 2/5] Documentation: mtd: add a DT property to set the number of dummy cycles

2015-08-24 Thread Cyrille Pitchen
Depending on the SPI clock frequency, the Fast Read op code and the
Single/Dual Data Rate mode, the number of dummy cycles can be tuned to
improve transfer speed.
The actual number of dummy cycles is specific for each memory model and is
provided by the manufacturer thanks to the memory datasheet.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt 
b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
index 2bee68103b01..4387567d8024 100644
--- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
+++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
@@ -19,6 +19,11 @@ Optional properties:
all chips and support for it can not be detected at runtime.
Refer to your chips' datasheet to check if this is supported
by your chip.
+- m25p,num-dummy-cycles : Set the number of dummy cycles for Fast Read 
commands.
+  Depending on the manufacturer additional dedicated
+  commands are sent to the flash memory so the
+  controller and the memory can agree on the number of
+  dummy cycles to use.
 
 Example:
 
@@ -29,4 +34,5 @@ Example:
reg = 0;
spi-max-frequency = 4000;
m25p,fast-read;
+   m25p,num-dummy-cycles = 8;
};
-- 
1.8.2.2

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


[PATCH linux-next v4 4/5] Documentation: atmel-quadspi: add binding file for Atmel QSPI driver

2015-08-24 Thread Cyrille Pitchen
This patch documents the DT bindings for the driver of the Atmel QSPI
controller embedded inside sama5d2x SoCs.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
Acked-by: Nicolas Ferre nicolas.fe...@atmel.com
---
 .../devicetree/bindings/mtd/atmel-quadspi.txt  | 29 ++
 1 file changed, 29 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt

diff --git a/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt 
b/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
new file mode 100644
index ..0b8d545bb198
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
@@ -0,0 +1,29 @@
+* Atmel Quad Serial Peripheral Interface (QSPI)
+
+Required properties:
+- compatible: should be atmel,sama5d2-qspi
+- reg:the first contains the register location and length,
+  the second contains the memory mapping address and length
+- interrupts: should contain the interrupt for the device
+- clocks: the phandle of the clock needed by the QSPI controller
+- #address-cells: should be 1
+- #size-cells:should be 0
+
+Example:
+
+spi@f002 {
+   compatible = atmel,sama5d2-qspi;
+   reg = 0xf002 0x100,
+ 0xd000 0x800;
+   interrupts = 52 IRQ_TYPE_LEVEL_HIGH 7;
+   clocks = spi0_clk;
+   #address-cells = 1;
+   #size-cells = 0;
+   pinctrl-names = default;
+   pinctrl-0 = pinctrl_spi0_default;
+   status = okay;
+
+   m25p80@0 {
+   ...
+   };
+};
-- 
1.8.2.2

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


[PATCH linux-next v4 5/5] mtd: atmel-quadspi: add driver for Atmel QSPI controller

2015-08-24 Thread Cyrille Pitchen
This driver add support to the new Atmel QSPI controller embedded into
sama5d2x SoCs. It expects a NOR memory to be connected to the QSPI
controller.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
Acked-by: Nicolas Ferre nicolas.fe...@atmel.com
---
 drivers/mtd/spi-nor/Kconfig |   7 +
 drivers/mtd/spi-nor/Makefile|   1 +
 drivers/mtd/spi-nor/atmel-quadspi.c | 876 
 3 files changed, 884 insertions(+)
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 89bf4c1faa2b..7a3d55429550 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -29,6 +29,13 @@ config SPI_FSL_QUADSPI
  This controller does not support generic SPI. It only supports
  SPI NOR.
 
+config SPI_ATMEL_QUADSPI
+   tristate Atmel Quad SPI Controller
+   depends on OF  HAS_DMA  (ARCH_AT91 || COMPILE_TEST)
+   help
+ This enables support for the Quad SPI controller in master mode.
+ We only connect the NOR to this controller now.
+
 config SPI_NXP_SPIFI
tristate NXP SPI Flash Interface (SPIFI)
depends on OF  (ARCH_LPC18XX || COMPILE_TEST)
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index e5ef8582..f5d23d7379bb 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_MTD_SPI_NOR)  += spi-nor.o
 obj-$(CONFIG_SPI_FSL_QUADSPI)  += fsl-quadspi.o
+obj-$(CONFIG_SPI_ATMEL_QUADSPI)+= atmel-quadspi.o
 obj-$(CONFIG_SPI_NXP_SPIFI)+= nxp-spifi.o
diff --git a/drivers/mtd/spi-nor/atmel-quadspi.c 
b/drivers/mtd/spi-nor/atmel-quadspi.c
new file mode 100644
index ..ada6f95782e4
--- /dev/null
+++ b/drivers/mtd/spi-nor/atmel-quadspi.c
@@ -0,0 +1,876 @@
+/*
+ * Driver for Atmel QSPI Controller
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen cyrille.pitc...@atmel.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see http://www.gnu.org/licenses/.
+ *
+ * This driver is based on drivers/mtd/spi-nor/fsl-quadspi.c from Freescale.
+ */
+
+#include linux/kernel.h
+#include linux/clk.h
+#include linux/module.h
+#include linux/platform_device.h
+#include linux/delay.h
+#include linux/dma-mapping.h
+#include linux/dmaengine.h
+#include linux/err.h
+#include linux/interrupt.h
+#include linux/mtd/mtd.h
+#include linux/mtd/partitions.h
+#include linux/mtd/spi-nor.h
+#include linux/platform_data/atmel.h
+#include linux/platform_data/dma-atmel.h
+#include linux/of.h
+
+#include linux/io.h
+#include linux/gpio.h
+#include linux/pinctrl/consumer.h
+
+/* QSPI register offsets */
+#define QSPI_CR  0x  /* Control Register */
+#define QSPI_MR  0x0004  /* Mode Register */
+#define QSPI_RD  0x0008  /* Receive Data Register */
+#define QSPI_TD  0x000c  /* Transmit Data Register */
+#define QSPI_SR  0x0010  /* Status Register */
+#define QSPI_IER 0x0014  /* Interrupt Enable Register */
+#define QSPI_IDR 0x0018  /* Interrupt Disable Register */
+#define QSPI_IMR 0x001c  /* Interrupt Mask Register */
+#define QSPI_SCR 0x0020  /* Serial Clock Register */
+
+#define QSPI_IAR 0x0030  /* Instruction Address Register */
+#define QSPI_ICR 0x0034  /* Instruction Code Register */
+#define QSPI_IFR 0x0038  /* Instruction Frame Register */
+
+#define QSPI_SMR 0x0040  /* Scrambling Mode Register */
+#define QSPI_SKR 0x0044  /* Scrambling Key Register */
+
+#define QSPI_WPMR0x00E4  /* Write Protection Mode Register */
+#define QSPI_WPSR0x00E8  /* Write Protection Status Register */
+
+#define QSPI_VERSION 0x00FC  /* Version Register */
+
+
+/* Bitfields in QSPI_CR (Control Register) */
+#define QSPI_CR_QSPIEN  BIT(0)
+#define QSPI_CR_QSPIDIS BIT(1)
+#define QSPI_CR_SWRST   BIT(7)
+#define QSPI_CR_LASTXFERBIT(24)
+
+/* Bitfields in QSPI_MR (Mode Register) */
+#define QSPI_MR_SSM BIT(0)
+#define QSPI_MR_LLB BIT(1)
+#define QSPI_MR_WDRBT   BIT(2)
+#define QSPI_MR_SMRMBIT(3)
+#define QSPI_MR_CSMODE_MASK GENMASK(5, 4)
+#define QSPI_MR_CSMODE_NOT_RELOADED (0  4)
+#define QSPI_MR_CSMODE_LASTXFER (1  4)
+#define QSPI_MR_CSMODE_SYSTEMATICALLY   (2  4)
+#define QSPI_MR_NBBITS_MASK GENMASK(11, 8)
+#define

[PATCH linux-next v4 0/5] add driver for Atmel QSPI controller

2015-08-24 Thread Cyrille Pitchen
ChangeLog

v4:
- add OF  HAS_DMA dependency in Kconfig for Atmel Quad SPI driver.
- return -ENOMEM instead of the return code of dma_mapping_error() as this
  function returns a boolean on ARM achitecture.
- add Acked-by: Nicolas Ferre nicolas.fe...@atmel.com for Atmel Quad
  SPI driver and its DT binding documentation.

v3:
- reword the comment which explains that spi_nor_set_protocol() is used by
  the spi-nor framework to notify lower layers, especially the (Q)SPI
  controller about a protocol change.
- change the definitions of register/bitfield macros in the Atmel QSPI
  controller driver: get rid of concatenation operator and use BIT and
  GENMASK macros when possible.
- use #define[SPACE] instead of #define[TAB]

v2:
- remove the patches to set the latency code of Spansion QSPI memories
  (support of Spansion memories may be submitted in later series).
- rename qspi node into spi in the DT example to fit ePAPR standard.
- remove the useless qspi0 label from the DT node example.
- remove the leading 0 from the size of the second memory region to make
  it consistent with the size of the first memory region.
- indent the DT bindings documentation to make it more readable.
- remove the useless .bus  = platform_bus_type, line from the
  platform driver definition.

v1:

This series of patches add support for the new Atmel QSPI controller
embedded inside sama5d2x SoCs.

These patches were first developped for linux-3.18-at91 and tested on a
sama5d27 Xplained ultra board, which embeds a Micron n25q128a13 QSPI NOR
flash memory. Then the series was adapted for mainline.

Cyrille Pitchen (5):
  mtd: spi-nor: notify (Q)SPI controller about protocol change
  Documentation: mtd: add a DT property to set the number of dummy
cycles
  mtd: spi-nor: allow to tune the number of dummy cycles
  Documentation: atmel-quadspi: add binding file for Atmel QSPI driver
  mtd: atmel-quadspi: add driver for Atmel QSPI controller

 .../devicetree/bindings/mtd/atmel-quadspi.txt  |  29 +
 .../devicetree/bindings/mtd/jedec,spi-nor.txt  |   6 +
 drivers/mtd/spi-nor/Kconfig|   7 +
 drivers/mtd/spi-nor/Makefile   |   1 +
 drivers/mtd/spi-nor/atmel-quadspi.c| 876 +
 drivers/mtd/spi-nor/spi-nor.c  | 118 ++-
 include/linux/mtd/spi-nor.h|  15 +
 7 files changed, 1033 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

-- 
1.8.2.2

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


[PATCH v3 3/5] mtd: spi-nor: allow to tune the number of dummy cycles

2015-07-27 Thread Cyrille Pitchen
The number of dummy cycles used during Fast Read commands can be reduced
to improve transfer performances. Each manufacturer has a dedicated set of
registers to provide the memory with the exact number of dummy cycles it
should expect. Both the memory and the (Q)SPI controller must agree on
this number of dummy cycles.

The number of dummy cycles can be found into the memory datasheet and
mostly depends on the SPI clock frequency, the Fast Read op code and the
Single/Dual Data Rate mode.

Probing JEDEC Serial Flash Discoverable Parameters (SFDP) tables would
only provide the driver with a high enough number of dummy cycles for each
Fast Read command to be used for all clock frequencies: this solution
would not be optimized.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 drivers/mtd/spi-nor/spi-nor.c | 97 ++-
 include/linux/mtd/spi-nor.h   |  2 +
 2 files changed, 80 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index d373a5fdf48b..2013e02e1116 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -119,24 +119,6 @@ static int read_cr(struct spi_nor *nor)
 }
 
 /*
- * Dummy Cycle calculation for different type of read.
- * It can be used to support more commands with
- * different dummy cycle requirements.
- */
-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
-{
-   switch (nor-flash_read) {
-   case SPI_NOR_FAST:
-   case SPI_NOR_DUAL:
-   case SPI_NOR_QUAD:
-   return 8;
-   case SPI_NOR_NORMAL:
-   return 0;
-   }
-   return 0;
-}
-
-/*
  * Write status register 1 byte
  * Returns negative if error occurred.
  */
@@ -1011,6 +993,81 @@ static int set_quad_mode(struct spi_nor *nor, struct 
flash_info *info)
}
 }
 
+static int micron_set_dummy_cycles(struct spi_nor *nor)
+{
+   int ret;
+   u8 val, mask;
+
+   /* read the Volatile Configuration Register (VCR) */
+   ret = nor-read_reg(nor, SPINOR_OP_RD_VCR, val, 1);
+   if (ret  0) {
+   dev_err(nor-dev, error %d reading VCR\n, ret);
+   return ret;
+   }
+
+   write_enable(nor);
+
+   /* update the number of dummy into the VCR */
+   mask = GENMASK(7, 4);
+   val = ~mask;
+   val |= (nor-read_dummy  4)  mask;
+   ret = nor-write_reg(nor, SPINOR_OP_WR_VCR, val, 1, 0);
+   if (ret  0) {
+   dev_err(nor-dev, error while writing VCR register\n);
+   return ret;
+   }
+
+   ret = spi_nor_wait_till_ready(nor);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
+/*
+ * Dummy Cycle calculation for different type of read.
+ * It can be used to support more commands with
+ * different dummy cycle requirements.
+ */
+static int spi_nor_read_dummy_cycles(struct spi_nor *nor,
+const struct flash_info *info)
+{
+   struct device_node *np = nor-dev-of_node;
+   u32 num_dummy_cycles;
+
+   if (np  !of_property_read_u32(np, m25p,num-dummy-cycles,
+   num_dummy_cycles)) {
+   nor-read_dummy = num_dummy_cycles;
+
+   /*
+* This switch block might be moved after the if...then...else
+* statement but it was not tested with all Spansion or Micron
+* memories.
+* Now the m25p,num-dummy-cycles property needs to be
+* explicitly set in the device tree so the switch statement is
+* executed. This should avoid unwanted side effects and keep
+* backward compatibility.
+*/
+   switch (JEDEC_MFR(info)) {
+   case CFI_MFR_ST:
+   return micron_set_dummy_cycles(nor);
+   default:
+   break;
+   }
+   } else {
+   switch (nor-flash_read) {
+   case SPI_NOR_FAST:
+   case SPI_NOR_DUAL:
+   case SPI_NOR_QUAD:
+   nor-read_dummy = 8;
+   case SPI_NOR_NORMAL:
+   nor-read_dummy = 0;
+   }
+   }
+
+   return 0;
+}
+
 static int spi_nor_check(struct spi_nor *nor)
 {
if (!nor-dev || !nor-read || !nor-write ||
@@ -1215,7 +1272,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
nor-addr_width = 3;
}
 
-   nor-read_dummy = spi_nor_read_dummy_cycles(nor);
+   ret = spi_nor_read_dummy_cycles(nor, info);
+   if (ret)
+   return ret;
 
dev_info(dev, %s (%lld Kbytes)\n, id-name,
(long long)mtd-size  10);
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 1bf6f11310ef..e03a4c4053d3 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -59,6 +59,8

[PATCH v3 2/5] Documentation: mtd: add a DT property to set the number of dummy cycles

2015-07-27 Thread Cyrille Pitchen
Depending on the SPI clock frequency, the Fast Read op code and the
Single/Dual Data Rate mode, the number of dummy cycles can be tuned to
improve transfer speed.
The actual number of dummy cycles is specific for each memory model and is
provided by the manufacturer thanks to the memory datasheet.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt 
b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
index 2bee68103b01..4387567d8024 100644
--- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
+++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
@@ -19,6 +19,11 @@ Optional properties:
all chips and support for it can not be detected at runtime.
Refer to your chips' datasheet to check if this is supported
by your chip.
+- m25p,num-dummy-cycles : Set the number of dummy cycles for Fast Read 
commands.
+  Depending on the manufacturer additional dedicated
+  commands are sent to the flash memory so the
+  controller and the memory can agree on the number of
+  dummy cycles to use.
 
 Example:
 
@@ -29,4 +34,5 @@ Example:
reg = 0;
spi-max-frequency = 4000;
m25p,fast-read;
+   m25p,num-dummy-cycles = 8;
};
-- 
1.8.2.2

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


[PATCH v3 0/5] add driver for Atmel QSPI controller

2015-07-27 Thread Cyrille Pitchen
ChangeLog

v3:
- reword the comment which explains that spi_nor_set_protocol() is used by
  the spi-nor framework to notify lower layers, especially the (Q)SPI
  controller about a protocol change.
- change the definitions of register/bitfield macros in the Atmel QSPI
  controller driver: get rid of concatenation operator and use BIT and
  GENMASK macros when possible.
- use #define[SPACE] instead of #define[TAB]

v2:
- remove the patches to set the latency code of Spansion QSPI memories
  (support of Spansion memories may be submitted in later series).
- rename qspi node into spi in the DT example to fit ePAPR standard.
- remove the useless qspi0 label from the DT node example.
- remove the leading 0 from the size of the second memory region to make
  it consistent with the size of the first memory region.
- indent the DT bindings documentation to make it more readable.
- remove the useless .bus  = platform_bus_type, line from the
  platform driver definition.

v1:

This series of patches add support for the new Atmel QSPI controller
embedded inside sama5d2x SoCs.

These patches were first developped for linux-3.18-at91 and tested on a
sama5d27 Xplained ultra board, which embeds a Micron n25q128a13 QSPI NOR
flash memory. Then the series was adapted for mainline.

Cyrille Pitchen (5):
  mtd: spi-nor: notify (Q)SPI controller about protocol change
  Documentation: mtd: add a DT property to set the number of dummy
cycles
  mtd: spi-nor: allow to tune the number of dummy cycles
  Documentation: atmel-quadspi: add binding file for Atmel QSPI driver
  mtd: atmel-quadspi: add driver for Atmel QSPI controller

 .../devicetree/bindings/mtd/atmel-quadspi.txt  |  29 +
 .../devicetree/bindings/mtd/jedec,spi-nor.txt  |   6 +
 drivers/mtd/spi-nor/Kconfig|   7 +
 drivers/mtd/spi-nor/Makefile   |   1 +
 drivers/mtd/spi-nor/atmel-quadspi.c| 877 +
 drivers/mtd/spi-nor/spi-nor.c  | 118 ++-
 include/linux/mtd/spi-nor.h|  15 +
 7 files changed, 1034 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

-- 
1.8.2.2

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


Re: [PATCH v2 5/5] mtd: atmel-quadspi: add driver for Atmel QSPI controller

2015-07-27 Thread Cyrille Pitchen
Hi Marek,

Le 22/07/2015 15:50, Marek Vasut a écrit :
 On Wednesday, July 22, 2015 at 03:17:10 PM, Cyrille Pitchen wrote:
 This driver add support to the new Atmel QSPI controller embedded into
 sama5d2x SoCs. It expects a NOR memory to be connected to the QSPI
 controller.

 Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
 ---
 [...]
 
 +/* QSPI register offsets */
 +#define QSPI_CR 0x  /* Control Register */
 +#define QSPI_MR 0x0004  /* Mode Register */
 +#define QSPI_RD 0x0008  /* Receive Data Register */
 +#define QSPI_TD 0x000c  /* Transmit Data Register */
 +#define QSPI_SR 0x0010  /* Status Register */
 +#define QSPI_IER0x0014  /* Interrupt Enable Register */
 +#define QSPI_IDR0x0018  /* Interrupt Disable Register */
 +#define QSPI_IMR0x001c  /* Interrupt Mask Register */
 +#define QSPI_SCR0x0020  /* Serial Clock Register */
 +
 +#define QSPI_IAR0x0030  /* Instruction Address Register */
 +#define QSPI_ICR0x0034  /* Instruction Code Register */
 +#define QSPI_IFR0x0038  /* Instruction Frame Register */
 +
 +#define QSPI_SMR0x0040  /* Scrambling Mode Register */
 +#define QSPI_SKR0x0044  /* Scrambling Key Register */
 +
 +#define QSPI_WPMR   0x00E4  /* Write Protection Mode Register */
 +#define QSPI_WPSR   0x00E8  /* Write Protection Status Register */
 +
 +#define QSPI_VERSION0x00FC  /* Version Register */
 +
 +/* Bitfields in QSPI_CR (Control Register) */
 +#define QSPI_CR_QSPIEN_OFFSET   0
 +#define QSPI_CR_QSPIEN_SIZE 1
 +#define QSPI_CR_QSPIDIS_OFFSET  1
 +#define QSPI_CR_QSPIDIS_SIZE1
 +#define QSPI_CR_SWRST_OFFSET7
 +#define QSPI_CR_SWRST_SIZE  1
 +#define QSPI_CR_LASTXFER_OFFSET 24
 +#define QSPI_CR_LASTXFER_SIZE   1
 +
 +/* Bitfields in QSPI_MR (Mode Register) */
 +#define QSPI_MR_SSM_OFFSET  0
 +#define QSPI_MR_SSM_SIZE1
 +#define QSPI_MR_LLB_OFFSET  1
 +#define QSPI_MR_LLB_SIZE1
 +#define QSPI_MR_WDRBT_OFFSET2
 +#define QSPI_MR_WDRBT_SIZE  1
 +#define QPSI_MR_SMRM_OFFSET 3
 +#define QSPI_MR_SMRM_SIZE   1
 +#define QSPI_MR_CSMODE_OFFSET   4
 +#define QSPI_MR_CSMODE_SIZE 2
 +#define QSPI_MR_NBBITS_OFFSET   8
 +#define QSPI_MR_NBBITS_SIZE 4
 +#define QSPI_MR_NBBITS_8_BIT0
 +#define QSPI_MR_NBBITS_9_BIT1
 +#define QSPI_MR_NBBITS_10_BIT   2
 +#define QSPI_MR_NBBITS_11_BIT   3
 +#define QSPI_MR_NBBITS_12_BIT   4
 +#define QSPI_MR_NBBITS_13_BIT   5
 +#define QSPI_MR_NBBITS_14_BIT   6
 +#define QSPI_MR_NBBITS_15_BIT   7
 +#define QSPI_MR_NBBITS_16_BIT   8
 
 You might want to turn this into something like:
 
 #define QSPI_NR_NBBITS(n) ((n) - 8)

done in the next series

 
 +#define QSPI_MR_DLYBCT_OFFSET   16
 +#define QSPI_MR_DLYBCT_SIZE 8
 +#define QSPI_MR_DLYCS_OFFSET24
 +#define QSPI_MR_DLYCS_SIZE  8
 
 [...]
 
 +/* Bitfields in QSPI_IFR (Instruction Frame Register) */
 +#define QSPI_IFR_WIDTH_OFFSET   0
 +#define QSPI_IFR_WIDTH_SIZE 3
 +#define QSPI_IFR_WIDTH_SINGLE_BIT_SPI   0
 +#define QSPI_IFR_WIDTH_DUAL_OUTPUT  1
 +#define QSPI_IFR_WIDTH_QUAD_OUTPUT  2
 +#define QSPI_IFR_WIDTH_DUAL_IO  3
 +#define QSPI_IFR_WIDTH_QUAD_IO  4
 +#define QSPI_IFR_WIDTH_DUAL_CMD 5
 +#define QSPI_IFR_WIDTH_QUAD_CMD 6
 
 Please use #define[SPACE] instead of inconsistent #define[TAB]
 

done in the next series. I also use BIT and GENMASK macros as much as possible
to define the register bit fields.

 [...]
 
 +/* Bit manipulation macros */
 +#define QSPI_BIT(name) \
 +(1  QSPI_##name##_OFFSET)
 +#define QSPI_BF(name, value) \
 +(((value)  ((1  QSPI_##name##_SIZE) - 1))  QSPI_##name##_OFFSET)
 +#define QSPI_BFEXT(name, value) \
 +(((value)  QSPI_##name##_OFFSET)  ((1  QSPI_##name##_SIZE) - 1))
 +#define QSPI_BFINS(name, value, old) \
 +(((old)  ~(((1  QSPI_##name##_SIZE) - 1)  QSPI_##name##_OFFSET)) \
 + | QSPI_BF(name, value))
 +
 +/* Register access macros */
 +#define qspi_readl(port, reg) \
 +readl_relaxed((port)-regs + QSPI_##reg)
 +#define qspi_writel(port, reg, value) \
 +writel_relaxed((value), (port)-regs + QSPI_##reg)
 +
 +#define qspi_readw(port, reg) \
 +readw_relaxed((port)-regs + QSPI_##reg)
 +#define qspi_writew(port, reg, value) \
 +writew_relaxed((value), (port)-regs + QSPI_##reg)
 +
 +#define qspi_readb(port, reg) \
 +readb_relaxed((port)-regs + QSPI_##reg)
 +#define qspi_writeb(port, reg, value

[PATCH v3 1/5] mtd: spi-nor: notify (Q)SPI controller about protocol change

2015-07-27 Thread Cyrille Pitchen
Once the Quad SPI mode has been enabled on a Micron flash memory, this
device expects ALL the following commands to use the SPI 4-4-4 protocol.
The (Q)SPI controller needs to be notified about the protocol change so it
can adapt and keep on dialoging with the Micron memory.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 drivers/mtd/spi-nor/spi-nor.c | 21 +
 include/linux/mtd/spi-nor.h   | 13 +
 2 files changed, 34 insertions(+)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index d78831b4422b..d373a5fdf48b 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -163,6 +163,22 @@ static inline int write_disable(struct spi_nor *nor)
return nor-write_reg(nor, SPINOR_OP_WRDI, NULL, 0, 0);
 }
 
+/*
+ * Let the spi-nor framework notify lower layers, especially the driver of the
+ * (Q)SPI controller, about the new protocol to be used. Indeed, once the
+ * spi-nor framework has sent manufacturer specific commands to a memory to
+ * enable its Quad SPI mode, it should immediately after tell the QSPI
+ * controller to use the very same Quad SPI protocol as expected by the memory.
+ */
+static inline int spi_nor_set_protocol(struct spi_nor *nor,
+  enum spi_protocol proto)
+{
+   if (nor-set_protocol)
+   return nor-set_protocol(nor, proto);
+
+   return 0;
+}
+
 static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
 {
return mtd-priv;
@@ -943,6 +959,11 @@ static int micron_quad_enable(struct spi_nor *nor)
return ret;
}
 
+   /* switch protocol to Quad CMD 4-4-4 */
+   ret = spi_nor_set_protocol(nor, SPI_PROTO_4_4_4);
+   if (ret)
+   return ret;
+
ret = spi_nor_wait_till_ready(nor);
if (ret)
return ret;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index e5409524bb0a..1bf6f11310ef 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -87,6 +87,16 @@ enum read_mode {
SPI_NOR_QUAD,
 };
 
+enum spi_protocol {
+   SPI_PROTO_1_1_1,/* SPI */
+   SPI_PROTO_1_1_2,/* Dual Output */
+   SPI_PROTO_1_1_4,/* Quad Output */
+   SPI_PROTO_1_2_2,/* Dual IO */
+   SPI_PROTO_1_4_4,/* Quad IO */
+   SPI_PROTO_2_2_2,/* Dual Command */
+   SPI_PROTO_4_4_4,/* Quad Command */
+};
+
 /**
  * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer
  * @wren:  command for Write Enable, or 0x00 for not required
@@ -149,6 +159,7 @@ enum spi_nor_option_flags {
  * read/write/erase/lock/unlock operations
  * @read_xfer: [OPTIONAL] the read fundamental primitive
  * @write_xfer:[OPTIONAL] the writefundamental primitive
+ * @set_protocol:  [OPTIONAL] notify about protocol change
  * @read_reg:  [DRIVER-SPECIFIC] read out the register
  * @write_reg: [DRIVER-SPECIFIC] write data to the register
  * @read:  [DRIVER-SPECIFIC] read data from the SPI NOR
@@ -185,6 +196,8 @@ struct spi_nor {
int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len,
int write_enable);
 
+   int (*set_protocol)(struct spi_nor *nor, enum spi_protocol proto);
+
int (*read)(struct spi_nor *nor, loff_t from,
size_t len, size_t *retlen, u_char *read_buf);
void (*write)(struct spi_nor *nor, loff_t to,
-- 
1.8.2.2

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


[PATCH v3 5/5] mtd: atmel-quadspi: add driver for Atmel QSPI controller

2015-07-27 Thread Cyrille Pitchen
This driver add support to the new Atmel QSPI controller embedded into
sama5d2x SoCs. It expects a NOR memory to be connected to the QSPI
controller.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 drivers/mtd/spi-nor/Kconfig |   7 +
 drivers/mtd/spi-nor/Makefile|   1 +
 drivers/mtd/spi-nor/atmel-quadspi.c | 877 
 3 files changed, 885 insertions(+)
 create mode 100644 drivers/mtd/spi-nor/atmel-quadspi.c

diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 64a4f0edabc7..bcdda302f5ab 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -28,4 +28,11 @@ config SPI_FSL_QUADSPI
  This enables support for the Quad SPI controller in master mode.
  We only connect the NOR to this controller now.
 
+config SPI_ATMEL_QUADSPI
+   tristate Atmel Quad SPI Controller
+   depends on (ARCH_AT91 || COMPILE_TEST)
+   help
+ This enables support for the Quad SPI controller in master mode.
+ We only connect the NOR to this controller now.
+
 endif # MTD_SPI_NOR
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 6a7ce1462247..243ea8a479ef 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_MTD_SPI_NOR)  += spi-nor.o
 obj-$(CONFIG_SPI_FSL_QUADSPI)  += fsl-quadspi.o
+obj-$(CONFIG_SPI_ATMEL_QUADSPI)+= atmel-quadspi.o
diff --git a/drivers/mtd/spi-nor/atmel-quadspi.c 
b/drivers/mtd/spi-nor/atmel-quadspi.c
new file mode 100644
index ..20dccd660b3c
--- /dev/null
+++ b/drivers/mtd/spi-nor/atmel-quadspi.c
@@ -0,0 +1,877 @@
+/*
+ * Driver for Atmel QSPI Controller
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen cyrille.pitc...@atmel.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see http://www.gnu.org/licenses/.
+ *
+ * This driver is based on drivers/mtd/spi-nor/fsl-quadspi.c from Freescale.
+ */
+
+#include linux/kernel.h
+#include linux/clk.h
+#include linux/module.h
+#include linux/platform_device.h
+#include linux/delay.h
+#include linux/dma-mapping.h
+#include linux/dmaengine.h
+#include linux/err.h
+#include linux/interrupt.h
+#include linux/mtd/mtd.h
+#include linux/mtd/partitions.h
+#include linux/mtd/spi-nor.h
+#include linux/platform_data/atmel.h
+#include linux/platform_data/dma-atmel.h
+#include linux/of.h
+
+#include linux/io.h
+#include linux/gpio.h
+#include linux/pinctrl/consumer.h
+
+/* QSPI register offsets */
+#define QSPI_CR  0x  /* Control Register */
+#define QSPI_MR  0x0004  /* Mode Register */
+#define QSPI_RD  0x0008  /* Receive Data Register */
+#define QSPI_TD  0x000c  /* Transmit Data Register */
+#define QSPI_SR  0x0010  /* Status Register */
+#define QSPI_IER 0x0014  /* Interrupt Enable Register */
+#define QSPI_IDR 0x0018  /* Interrupt Disable Register */
+#define QSPI_IMR 0x001c  /* Interrupt Mask Register */
+#define QSPI_SCR 0x0020  /* Serial Clock Register */
+
+#define QSPI_IAR 0x0030  /* Instruction Address Register */
+#define QSPI_ICR 0x0034  /* Instruction Code Register */
+#define QSPI_IFR 0x0038  /* Instruction Frame Register */
+
+#define QSPI_SMR 0x0040  /* Scrambling Mode Register */
+#define QSPI_SKR 0x0044  /* Scrambling Key Register */
+
+#define QSPI_WPMR0x00E4  /* Write Protection Mode Register */
+#define QSPI_WPSR0x00E8  /* Write Protection Status Register */
+
+#define QSPI_VERSION 0x00FC  /* Version Register */
+
+
+/* Bitfields in QSPI_CR (Control Register) */
+#define QSPI_CR_QSPIEN  BIT(0)
+#define QSPI_CR_QSPIDIS BIT(1)
+#define QSPI_CR_SWRST   BIT(7)
+#define QSPI_CR_LASTXFERBIT(24)
+
+/* Bitfields in QSPI_MR (Mode Register) */
+#define QSPI_MR_SSM BIT(0)
+#define QSPI_MR_LLB BIT(1)
+#define QSPI_MR_WDRBT   BIT(2)
+#define QSPI_MR_SMRMBIT(3)
+#define QSPI_MR_CSMODE_MASK GENMASK(5, 4)
+#define QSPI_MR_CSMODE_NOT_RELOADED (0  4)
+#define QSPI_MR_CSMODE_LASTXFER (1  4)
+#define QSPI_MR_CSMODE_SYSTEMATICALLY   (2  4)
+#define QSPI_MR_NBBITS_MASK GENMASK(11, 8)
+#define QSPI_MR_NBBITS(n)   n) - 8)  8)  
QSPI_MR_NBBITS_MASK)
+#define QSPI_MR_DLYBCT_MASK GENMASK(23, 16)
+#define QSPI_MR_DLYBCT(n)   (((n)  16

[PATCH v3 4/5] Documentation: atmel-quadspi: add binding file for Atmel QSPI driver

2015-07-27 Thread Cyrille Pitchen
This patch documents the DT bindings for the driver of the Atmel QSPI
controller embedded inside sama5d2x SoCs.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 .../devicetree/bindings/mtd/atmel-quadspi.txt  | 29 ++
 1 file changed, 29 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-quadspi.txt

diff --git a/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt 
b/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
new file mode 100644
index ..0b8d545bb198
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
@@ -0,0 +1,29 @@
+* Atmel Quad Serial Peripheral Interface (QSPI)
+
+Required properties:
+- compatible: should be atmel,sama5d2-qspi
+- reg:the first contains the register location and length,
+  the second contains the memory mapping address and length
+- interrupts: should contain the interrupt for the device
+- clocks: the phandle of the clock needed by the QSPI controller
+- #address-cells: should be 1
+- #size-cells:should be 0
+
+Example:
+
+spi@f002 {
+   compatible = atmel,sama5d2-qspi;
+   reg = 0xf002 0x100,
+ 0xd000 0x800;
+   interrupts = 52 IRQ_TYPE_LEVEL_HIGH 7;
+   clocks = spi0_clk;
+   #address-cells = 1;
+   #size-cells = 0;
+   pinctrl-names = default;
+   pinctrl-0 = pinctrl_spi0_default;
+   status = okay;
+
+   m25p80@0 {
+   ...
+   };
+};
-- 
1.8.2.2

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


[PATCH v8 0/2] mfd: flexcom: add a driver for Flexcom

2015-07-24 Thread Cyrille Pitchen
ChangeLog

v8:
- fix the name of the spi node in the DT example: from spi@f8034400 to
  spi@2,0
- use the return code of op_property_read_u32_index() instead of -EINVAL
  to report error.
- add Acked-by from Nicolas Ferre

v7:
- read the operating mode from the very first u32 of the reg property from
  the first available child node (should be unique).
- update the DT bindings documentation accordingly.

v6:
- select the operating mode according to the compatible DT property of
  the first available child node (should be unique).
- remove the atmel,flexcom-mode DT property so the need of a header file
  defining macros for the possible values of this deprecated property.

v5:
- create a header file containing macros used by DT bindings
- use numeric constants instead of strings to select the Flexcom mode
- change the license to GPL v2
- update the DT binding documentation to make it more readable and add
  references to USART, SPI and I2C DT binding documentations. remove the
  useless label in the Example section.
- change the register prefix from FX_ to FLEX_ to match the Flexcom
  programmer datasheet.
- rename some variables to make them more understandable.

v4:
- check clk_prepare_enable() return code in atmel_flexcom_probe()
- add a commit message to the DT binding patch

v3:
- remove MODULE_ALIAS()
- add Acked-by from Boris Brezillon and Alexandre Belloni

v2:
- enhance the documentation of DT bindings and change the way the ranges
  property is used.
- replace __raw_readl() and __raw_writel() by readl() and writel().
- change the module license to GPL for v2 or later
- print the selected flexcom mode after the hardware version

v1:
This series of patches a support to the Atmel Flexcom, a wrapper which
integrates an USART, a SPI controller and a TWI controller. Only one
peripheral can be used at a time. The active function is selected though
the Flexcom Mode Register.

Cyrille Pitchen (2):
  mfd: devicetree: add bindings for Atmel Flexcom
  mfd: atmel-flexcom: add a driver for Atmel Flexible Serial
Communication Unit

 .../devicetree/bindings/mfd/atmel-flexcom.txt  |  68 +
 drivers/mfd/Kconfig|  11 ++
 drivers/mfd/Makefile   |   1 +
 drivers/mfd/atmel-flexcom.c| 113 +
 4 files changed, 193 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
 create mode 100644 drivers/mfd/atmel-flexcom.c

-- 
1.8.2.2

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


[PATCH v8 1/2] mfd: devicetree: add bindings for Atmel Flexcom

2015-07-24 Thread Cyrille Pitchen
This patch documents the DT bindings for the Atmel Flexcom which will be
introduced by sama5d2x SoCs. These bindings will be used by the actual
Flexcom driver to be sent in another patch.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
Acked-by: Nicolas Ferre nicolas.fe...@atmel.com
---
 .../devicetree/bindings/mfd/atmel-flexcom.txt  | 68 ++
 1 file changed, 68 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt

diff --git a/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt 
b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
new file mode 100644
index ..588d527dbfa7
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
@@ -0,0 +1,68 @@
+* Device tree bindings for Atmel Flexcom (Flexible Serial Communication Unit)
+
+The Atmel Flexcom is just a wrapper which embeds a SPI controller, an I2C
+controller and an USART. Only one function can be used at a time and is chosen
+at boot time according to the device tree.
+
+Required properties:
+- compatible:  Should be atmel,sama5d2-flexcom
+- reg: Should be the pair (offset, size) for the Flexcom
+   dedicated I/O registers (without USART, TWI or SPI
+   registers).
+- clocks:  Should be the Flexcom peripheral clock from PMC.
+- #address-cells:  Should be 2
+- #size-cells: Should be 1
+- ranges:  Should be a list of ranges.
+   One range per peripheral wrapped by the Flexcom. So each
+   range is a triplet (child_addr, parent_addr, size). The
+   first u32 of child_addr is the value to be set in the
+   Operating Mode bitfield of the Flexcom Mode Register.
+   Then parent_addr stores the base address of the
+   corresponding peripheral in the system memory. Finally,
+   size if the size of the memory region of this
+   peripheral.
+
+Required child:
+A single available child for the serial controller to enable.
+
+Required properties of this child:
+- reg: Should be a pair (child_addr, size) with child_addr
+   matching one of the parent ranges.
+- clocks:  Should be the very same phandle as for the parent's one.
+
+Other properties remain unchanged. See documentation of the respective device:
+- ../serial/atmel-usart.txt
+- ../spi/spi_atmel.txt
+- ../i2c/i2c-at91.txt
+
+Example:
+
+flexcom@f8034000 {
+   compatible = atmel,sama5d2-flexcom;
+   reg = 0xf8034000 0x200;
+   clocks = flx0_clk;
+   #address-cells = 2;
+   #size-cells = 1;
+   ranges = 1 0 0xf8034200 0x200  /* opmode 1: USART */
+ 2 0 0xf8034400 0x200  /* opmode 2: SPI */
+ 3 0 0xf8034600 0x200;/* opmode 3: I2C */
+
+   spi@2,0 {
+   compatible = atmel,at91rm9200-spi;
+   reg = 2 0 0x200;
+   interrupts = 19 IRQ_TYPE_LEVEL_HIGH 7;
+   pinctrl-names = default;
+   pinctrl-0 = pinctrl_flx0_default;
+   #address-cells = 1;
+   #size-cells = 0;
+   clocks = flx0_clk;
+   clock-names = spi_clk;
+   atmel,fifo-size = 32;
+
+   mtd_dataflash@0 {
+   compatible = atmel,at25f512b;
+   reg = 0;
+   spi-max-frequency = 2000;
+   };
+   };
+};
-- 
1.8.2.2

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


[PATCH v8 2/2] mfd: atmel-flexcom: add a driver for Atmel Flexible Serial Communication Unit

2015-07-24 Thread Cyrille Pitchen
This driver supports the new Atmel Flexcom. The Flexcom is a wrapper which
integrates one SPI controller, one I2C controller and one USART. Only one
function can be enabled at a time. This driver selects the function once
for all, when the Flexcom is probed, using the reg property of the first
(should be unique) available DT child node.

This driver has chosen to present the Flexcom to the system as a MFD so
the implementation is seamless for the existing Atmel SPI, I2C and USART
drivers.

Also the Flexcom embeds FIFOs: the latest patches of the SPI, I2C and
USART drivers take advantage of this new feature.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
Acked-by: Nicolas Ferre nicolas.fe...@atmel.com
---
 drivers/mfd/Kconfig |  11 +
 drivers/mfd/Makefile|   1 +
 drivers/mfd/atmel-flexcom.c | 113 
 3 files changed, 125 insertions(+)
 create mode 100644 drivers/mfd/atmel-flexcom.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 653815950aa2..2c75472c679c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -60,6 +60,17 @@ config MFD_AAT2870_CORE
  additional drivers must be enabled in order to use the
  functionality of the device.
 
+config MFD_ATMEL_FLEXCOM
+   tristate Atmel Flexcom (Flexible Serial Communication Unit)
+   select MFD_CORE
+   depends on OF
+   help
+ Select this to get support for Atmel Flexcom. This is a wrapper
+ which embeds a SPI controller, a I2C controller and a USART. Only
+ one function can be used at a time. The choice is done at boot time
+ by the probe function of this MFD driver according to a device tree
+ property.
+
 config MFD_ATMEL_HLCDC
tristate Atmel HLCDC (High-end LCD Controller)
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index ea40e076cb61..0705eb2d873d 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -160,6 +160,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
 obj-$(CONFIG_TPS65911_COMPARATOR)  += tps65911-comparator.o
 obj-$(CONFIG_MFD_TPS65090) += tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
+obj-$(CONFIG_MFD_ATMEL_FLEXCOM)+= atmel-flexcom.o
 obj-$(CONFIG_MFD_ATMEL_HLCDC)  += atmel-hlcdc.o
 obj-$(CONFIG_MFD_INTEL_MSIC)   += intel_msic.o
 obj-$(CONFIG_MFD_PALMAS)   += palmas.o
diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
new file mode 100644
index ..b0c6f5556b17
--- /dev/null
+++ b/drivers/mfd/atmel-flexcom.c
@@ -0,0 +1,113 @@
+/*
+ * Driver for Atmel Flexcom
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen cyrille.pitc...@atmel.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see http://www.gnu.org/licenses/.
+ */
+
+#include linux/module.h
+#include linux/types.h
+#include linux/kernel.h
+#include linux/platform_device.h
+#include linux/of.h
+#include linux/of_platform.h
+#include linux/err.h
+#include linux/io.h
+#include linux/clk.h
+
+/* I/O register offsets */
+#define FLEX_MR0x0 /* Mode Register */
+#define FLEX_VERSION   0xfc/* Version Register */
+
+/* Mode Register bit fields */
+#define FLEX_MR_OPMODE_MASK0x3
+#define FLEX_MR_OPMODE_NO_COM  0x0
+#define FLEX_MR_OPMODE_USART   0x1
+#define FLEX_MR_OPMODE_SPI 0x2
+#define FLEX_MR_OPMODE_TWI 0x3
+
+
+static int atmel_flexcom_probe(struct platform_device *pdev)
+{
+   struct device_node *child, *np = pdev-dev.of_node;
+   struct clk *clk;
+   struct resource *res;
+   void __iomem *base;
+   u32 opmode;
+   int err;
+
+   child = of_get_next_available_child(np, NULL);
+   if (!child)
+   return -ENODEV;
+
+   /*
+* The Operating Mode is stored into the first u32 of the reg property
+* of the child.
+*/
+   err = of_property_read_u32_index(child, reg, 0, opmode);
+   of_node_put(child);
+   if (err)
+   return err;
+
+   if ((opmode == FLEX_MR_OPMODE_NO_COM) ||
+   (opmode  ~FLEX_MR_OPMODE_MASK))
+   return -EINVAL;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   base = devm_ioremap_resource(pdev-dev, res);
+   if (IS_ERR(base))
+   return PTR_ERR(base);
+
+   clk = devm_clk_get(pdev-dev, NULL);
+   if (IS_ERR(clk))
+   return PTR_ERR(clk);
+
+   err

Re: [PATCH v6 2/2] mfd: atmel-flexcom: add a driver for Atmel Flexible Serial Communication Unit

2015-07-23 Thread Cyrille Pitchen
Hi all,

Le 23/07/2015 14:50, Boris Brezillon a écrit :
 On Thu, 23 Jul 2015 10:13:11 +0100
 Lee Jones lee.jo...@linaro.org wrote:
 
 On Thu, 23 Jul 2015, Boris Brezillon wrote:

 Hi Lee,

 On Thu, 23 Jul 2015 08:32:17 +0100
 Lee Jones lee.jo...@linaro.org wrote:

 On Wed, 22 Jul 2015, Cyrille Pitchen wrote:
 + for_each_child_of_node(np, child) {
 + const char *compatible;
 + int cplen;
 +
 + if (!of_device_is_available(child))
 + continue;
 +
 + compatible = of_get_property(child, compatible, cplen);
 + if (!compatible || strlen(compatible)  cplen)
 + continue;
 +
 + if (strstr(compatible, -usart)) {
 + opmode = FLEX_MR_OPMODE_USART;
 + break;
 + }
 +
 + if (strstr(compatible, -spi)) {
 + opmode = FLEX_MR_OPMODE_SPI;
 + break;
 + }
 +
 + if (strstr(compatible, -i2c)) {
 + opmode = FLEX_MR_OPMODE_TWI;
 + break;
 + }
 + }

 From what I understand Flexcom is a wrapper which can sit above any
 number of SPI, I2C and/or UART devices.  Devices which you don't
 really have any control over (source code wise).  So wouldn't it be
 better to match on the details you do have control over i.e. the node
 name, rather than the compatible string?

 I would personally match on of_find_node_by_name() to future-proof
 your implementation.

 Actually, I think using compatible strings is more future-proof than
 using the node names, because nothing in the DT bindings doc enforce the
 node name, and usually what we use to attach a node to a specific
 driver is the compatible string (this one is specified in the bindings
 doc).

 I know what you're saying, but what if someone uses the Flexcom driver
 to wrap a different type of SPI driver where (for instance) the
 compatible string used is name-newtype.  Then we'd have to keep
 adding more lines here to accommodate.

 Whereas if we used the child node name which only pertains to _this_
 driver, we would then have full control and know that (unless it
 Flexcom is used for a completely different type of serial controller)
 we wouldn't have to keep expanding the code to accommodate.
 
 You're right about the complexity implied by the compat string
 maintenance, but I still think using node names to detect the mode is
 a bad idea.
 
 Let's take another example making both solution unsuitable: what if
 the flexcom-v2 exposes 2 devices of the same type, they will both have
 the same name and the same compatible string, and we'll have no way to
 detect the appropriate mode. That's why I think none of our suggestion
 is future-proof.
 

 Regarding the implementation itself, I would match the child node with
 an of_device_id table rather than trying to find a specific substring
 in the compatible string, but I think that's only a matter of taste.

 You mean duplicate each of the supported device's compatible strings
 in this driver, then fetch the attributed of_match_device()-data
 value?

 
 Yes, and that's definitely not a good idea, but I think Cyrille has
 found a better approach (I'll let him explain).

Indeed, what about taking advantage of the ranges property?

For the Flexcom:
#address-cells = 2;
#size-cells = 1;
ranges = 1 0 0xf8034200 0x200/* opmode 1: USART */
  2 0 0xf8034400 0x200/* opmode 2: SPI */
  3 0 0xf8034600 0x200;  /* opmode 3: I2C */

Then for the single available child (for instance the SPI controller):
reg = 2 0 0x200;

So the Operating Mode to be set into the Flexcom Mode Register is read from
the very first u32 of the reg property of the child.

No need to introduce any new DT property and the mapping remains easy to
maintain to follow hardware upgrades.

More details in v7 series.

 
 Best Regards,
 
 Boris
 

Best Regards,

Cyrille
--
To unsubscribe from this list: send the line unsubscribe devicetree in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 1/2] mfd: devicetree: add bindings for Atmel Flexcom

2015-07-23 Thread Cyrille Pitchen
This patch documents the DT bindings for the Atmel Flexcom which will be
introduced by sama5d2x SoCs. These bindings will be used by the actual
Flexcom driver to be sent in another patch.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 .../devicetree/bindings/mfd/atmel-flexcom.txt  | 68 ++
 1 file changed, 68 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt

diff --git a/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt 
b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
new file mode 100644
index ..a63226b7a9cb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
@@ -0,0 +1,68 @@
+* Device tree bindings for Atmel Flexcom (Flexible Serial Communication Unit)
+
+The Atmel Flexcom is just a wrapper which embeds a SPI controller, an I2C
+controller and an USART. Only one function can be used at a time and is chosen
+at boot time according to the device tree.
+
+Required properties:
+- compatible:  Should be atmel,sama5d2-flexcom
+- reg: Should be the pair (offset, size) for the Flexcom
+   dedicated I/O registers (without USART, TWI or SPI
+   registers).
+- clocks:  Should be the Flexcom peripheral clock from PMC.
+- #address-cells:  Should be 2
+- #size-cells: Should be 1
+- ranges:  Should be a list of ranges.
+   One range per peripheral wrapped by the Flexcom. So each
+   range is a triplet (child_addr, parent_addr, size). The
+   first u32 of child_addr is the value to be set in the
+   Operating Mode bitfield of the Flexcom Mode Register.
+   Then parent_addr stores the base address of the
+   corresponding peripheral in the system memory. Finally,
+   size if the size of the memory region of this
+   peripheral.
+
+Required child:
+A single available child for the serial controller to enable.
+
+Required properties of this child:
+- reg: Should be a pair (child_addr, size) with child_addr
+   matching one of the parent ranges.
+- clocks:  Should be the very same phandle as for the parent's one.
+
+Other properties remain unchanged. See documentation of the respective device:
+- ../serial/atmel-usart.txt
+- ../spi/spi_atmel.txt
+- ../i2c/i2c-at91.txt
+
+Example:
+
+flexcom@f8034000 {
+   compatible = atmel,sama5d2-flexcom;
+   reg = 0xf8034000 0x200;
+   clocks = flx0_clk;
+   #address-cells = 2;
+   #size-cells = 1;
+   ranges = 1 0 0xf8034200 0x200  /* opmode 1: USART */
+ 2 0 0xf8034400 0x200  /* opmode 2: SPI */
+ 3 0 0xf8034600 0x200;/* opmode 3: I2C */
+
+   spi@f8034400 {
+   compatible = atmel,at91rm9200-spi;
+   reg = 2 0 0x200;
+   interrupts = 19 IRQ_TYPE_LEVEL_HIGH 7;
+   pinctrl-names = default;
+   pinctrl-0 = pinctrl_flx0_default;
+   #address-cells = 1;
+   #size-cells = 0;
+   clocks = flx0_clk;
+   clock-names = spi_clk;
+   atmel,fifo-size = 32;
+
+   mtd_dataflash@0 {
+   compatible = atmel,at25f512b;
+   reg = 0;
+   spi-max-frequency = 2000;
+   };
+   };
+};
-- 
1.8.2.2

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


[PATCH v7 2/2] mfd: atmel-flexcom: add a driver for Atmel Flexible Serial Communication Unit

2015-07-23 Thread Cyrille Pitchen
This driver supports the new Atmel Flexcom. The Flexcom is a wrapper which
integrates one SPI controller, one I2C controller and one USART. Only one
function can be enabled at a time. This driver selects the function once
for all, when the Flexcom is probed, using the reg property of the first
(should be unique) available DT child node.

This driver has chosen to present the Flexcom to the system as a MFD so
the implementation is seamless for the existing Atmel SPI, I2C and USART
drivers.

Also the Flexcom embeds FIFOs: the latest patches of the SPI, I2C and
USART drivers take advantage of this new feature.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 drivers/mfd/Kconfig |  11 +
 drivers/mfd/Makefile|   1 +
 drivers/mfd/atmel-flexcom.c | 113 
 3 files changed, 125 insertions(+)
 create mode 100644 drivers/mfd/atmel-flexcom.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 653815950aa2..2c75472c679c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -60,6 +60,17 @@ config MFD_AAT2870_CORE
  additional drivers must be enabled in order to use the
  functionality of the device.
 
+config MFD_ATMEL_FLEXCOM
+   tristate Atmel Flexcom (Flexible Serial Communication Unit)
+   select MFD_CORE
+   depends on OF
+   help
+ Select this to get support for Atmel Flexcom. This is a wrapper
+ which embeds a SPI controller, a I2C controller and a USART. Only
+ one function can be used at a time. The choice is done at boot time
+ by the probe function of this MFD driver according to a device tree
+ property.
+
 config MFD_ATMEL_HLCDC
tristate Atmel HLCDC (High-end LCD Controller)
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index ea40e076cb61..0705eb2d873d 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -160,6 +160,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
 obj-$(CONFIG_TPS65911_COMPARATOR)  += tps65911-comparator.o
 obj-$(CONFIG_MFD_TPS65090) += tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
+obj-$(CONFIG_MFD_ATMEL_FLEXCOM)+= atmel-flexcom.o
 obj-$(CONFIG_MFD_ATMEL_HLCDC)  += atmel-hlcdc.o
 obj-$(CONFIG_MFD_INTEL_MSIC)   += intel_msic.o
 obj-$(CONFIG_MFD_PALMAS)   += palmas.o
diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
new file mode 100644
index ..0d06b70696b0
--- /dev/null
+++ b/drivers/mfd/atmel-flexcom.c
@@ -0,0 +1,113 @@
+/*
+ * Driver for Atmel Flexcom
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen cyrille.pitc...@atmel.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see http://www.gnu.org/licenses/.
+ */
+
+#include linux/module.h
+#include linux/types.h
+#include linux/kernel.h
+#include linux/platform_device.h
+#include linux/of.h
+#include linux/of_platform.h
+#include linux/err.h
+#include linux/io.h
+#include linux/clk.h
+
+/* I/O register offsets */
+#define FLEX_MR0x0 /* Mode Register */
+#define FLEX_VERSION   0xfc/* Version Register */
+
+/* Mode Register bit fields */
+#define FLEX_MR_OPMODE_MASK0x3
+#define FLEX_MR_OPMODE_NO_COM  0x0
+#define FLEX_MR_OPMODE_USART   0x1
+#define FLEX_MR_OPMODE_SPI 0x2
+#define FLEX_MR_OPMODE_TWI 0x3
+
+
+static int atmel_flexcom_probe(struct platform_device *pdev)
+{
+   struct device_node *child, *np = pdev-dev.of_node;
+   struct clk *clk;
+   struct resource *res;
+   void __iomem *base;
+   u32 opmode;
+   int err;
+
+   child = of_get_next_available_child(np, NULL);
+   if (!child)
+   return -ENODEV;
+
+   /*
+* The Operating Mode is stored into the first u32 of the reg property
+* of the child.
+*/
+   err = of_property_read_u32_index(child, reg, 0, opmode);
+   of_node_put(child);
+   if (err)
+   return -EINVAL;
+
+   if ((opmode == FLEX_MR_OPMODE_NO_COM) ||
+   (opmode  ~FLEX_MR_OPMODE_MASK))
+   return -EINVAL;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   base = devm_ioremap_resource(pdev-dev, res);
+   if (IS_ERR(base))
+   return PTR_ERR(base);
+
+   clk = devm_clk_get(pdev-dev, NULL);
+   if (IS_ERR(clk))
+   return PTR_ERR(clk);
+
+   err = clk_prepare_enable(clk);
+   if (err

[PATCH v7 0/2] mfd: flexcom: add a driver for Flexcom

2015-07-23 Thread Cyrille Pitchen
ChangeLog

v7:
- read the operating mode from the very first u32 of the reg property from
  the first available child node (should be unique).
- update the DT bindings documentation accordingly.

v6:
- select the operating mode according to the compatible DT property of
  the first available child node (should be unique).
- remove the atmel,flexcom-mode DT property so the need of a header file
  defining macros for the possible values of this deprecated property.

v5:
- create a header file containing macros used by DT bindings
- use numeric constants instead of strings to select the Flexcom mode
- change the license to GPL v2
- update the DT binding documentation to make it more readable and add
  references to USART, SPI and I2C DT binding documentations. remove the
  useless label in the Example section.
- change the register prefix from FX_ to FLEX_ to match the Flexcom
  programmer datasheet.
- rename some variables to make them more understandable.

v4:
- check clk_prepare_enable() return code in atmel_flexcom_probe()
- add a commit message to the DT binding patch

v3:
- remove MODULE_ALIAS()
- add Acked-by from Boris Brezillon and Alexandre Belloni

v2:
- enhance the documentation of DT bindings and change the way the ranges
  property is used.
- replace __raw_readl() and __raw_writel() by readl() and writel().
- change the module license to GPL for v2 or later
- print the selected flexcom mode after the hardware version

v1:
This series of patches a support to the Atmel Flexcom, a wrapper which
integrates an USART, a SPI controller and a TWI controller. Only one
peripheral can be used at a time. The active function is selected though
the Flexcom Mode Register.

Cyrille Pitchen (2):
  mfd: devicetree: add bindings for Atmel Flexcom
  mfd: atmel-flexcom: add a driver for Atmel Flexible Serial
Communication Unit

 .../devicetree/bindings/mfd/atmel-flexcom.txt  |  68 +
 drivers/mfd/Kconfig|  11 ++
 drivers/mfd/Makefile   |   1 +
 drivers/mfd/atmel-flexcom.c| 113 +
 4 files changed, 193 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
 create mode 100644 drivers/mfd/atmel-flexcom.c

-- 
1.8.2.2

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


Re: [PATCH v2 1/5] mtd: spi-nor: notify (Q)SPI controller about protocol change

2015-07-22 Thread Cyrille Pitchen
Hi Marek,

Le 22/07/2015 15:41, Marek Vasut a écrit :
 On Wednesday, July 22, 2015 at 03:17:06 PM, Cyrille Pitchen wrote:
 Once the Quad SPI mode has been enabled on a Micron flash memory, this
 device expects ALL the following commands to use the SPI 4-4-4 protocol.
 The (Q)SPI controller needs to be notified about the protocol change so it
 can adapt and keep on dialoging with the Micron memory.

 Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
 ---
  drivers/mtd/spi-nor/spi-nor.c | 17 +
  include/linux/mtd/spi-nor.h   | 13 +
  2 files changed, 30 insertions(+)

 diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
 index d78831b4422b..93627d4e6be8 100644
 --- a/drivers/mtd/spi-nor/spi-nor.c
 +++ b/drivers/mtd/spi-nor/spi-nor.c
 @@ -163,6 +163,18 @@ static inline int write_disable(struct spi_nor *nor)
  return nor-write_reg(nor, SPINOR_OP_WRDI, NULL, 0, 0);
  }

 +/*
 + * Notify the (Q)SPI controller about the new protocol to be used.
 
 Hi!
 
 Can you please just reword this a little, so that it is absolutelly clear
 even to the less bright of us (like me) that this is a notification coming
 from the upper layers (ie. the spi-nor framework) toward the hardware ?
 
Sure, no problem! what about the following?

/*
 * Let the spi-nor framework notify lower layers, especially the driver of the
 * (Q)SPI controller, about the new protocol to be used. Indeed, once the
 * spi-nor framework has sent manufacturer specific commands to a memory to
 * enable its Quad SPI mode, it should immediately after tell the QSPI
 * controller to use the very same Quad SPI protocol as expected by the memory.
 */

 + */
 +static inline int spi_nor_set_protocol(struct spi_nor *nor,
 +   enum spi_protocol proto)
 +{
 +if (nor-set_protocol)
 +return nor-set_protocol(nor, proto);
 +
 +return 0;
 +}
 +
  static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
  {
  return mtd-priv;
 
 [...]
 
 Best regards,
 Marek Vasut
 
Best regards,

Cyrille
--
To unsubscribe from this list: send the line unsubscribe devicetree in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 2/5] Documentation: mtd: add a DT property to set the number of dummy cycles

2015-07-22 Thread Cyrille Pitchen
Hi Marek,

Le 22/07/2015 15:43, Marek Vasut a écrit :
 On Wednesday, July 22, 2015 at 03:17:07 PM, Cyrille Pitchen wrote:
 Depending on the SPI clock frequency, the Fast Read op code and the
 Single/Dual Data Rate mode, the number of dummy cycles can be tuned to
 improve transfer speed.
 The actual number of dummy cycles is specific for each memory model and is
 provided by the manufacturer thanks to the memory datasheet.

 Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
 ---
  Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt | 6 ++
  1 file changed, 6 insertions(+)

 diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
 b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt index
 2bee68103b01..4387567d8024 100644
 --- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
 +++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
 @@ -19,6 +19,11 @@ Optional properties:
 all chips and support for it can not be detected at
 runtime. Refer to your chips' datasheet to check if this is supported by
 your chip.
 +- m25p,num-dummy-cycles : Set the number of dummy cycles for Fast Read
 commands. +  Depending on the manufacturer
 additional dedicated +  commands are sent to the
 flash memory so the +  controller and the memory
 can agree on the number of +  dummy cycles to use.
 
 Can't you just try negotiating this value at probe time, starting with some
 high value and see how low you can get with the negotiations ? This way, 
 you'd 
 be able to effectively auto-detect this value at probe-time.
 
 I might be wrong though :)
 
I don't know whether it would be reliable enough. It is the exact same idea as
for the latency code used by Spansion QSPI memories. Micron memories allow to
skip the step of converting the number of dummy cycles into a latency code, you
directly program the right number of dummy cycles into a Micron specific
register, the Volatile Configuration Register.

However for both manufacturers the number of dummy cycles to use during Fast 
Read commands is given though tables found into the memory datasheet. The
number of dummy cycles depends on the Fast Read command, the SPI bus clock
frequency and the Single/Dual Data Rate mode.

It should be confirmed by Quad SPI memory manufacturers but since the number of
dummy cycles depends on the bus clock frequency, I guess the values provided by
the datasheets are recommendations. I think a too low value should not be so
easy to detect. For a given frequency one Fast Read command may succeed whereas
the same command with the very same number of dummy cycles might fail on the
next try. To be honest, I'm not sure about the memory behavior in limit
conditions so maybe the command will always succeed or always fail.

Also we can't be sure the read data are valid if we don't write them first. So
we would have to save the original data to restore them at the end of the
probing. Writing data at each probe would also reduce the memory lifetime. We
should also be aware of the bad blocks, which is more a job for upper layers.

It would be interesting to have some feedbacks from Micron, Spansion or other
QSPI memory manufacturer :)

 Best regards,
 Marek Vasut
 
Best regards,

Cyrille
--
To unsubscribe from this list: send the line unsubscribe devicetree in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 1/2] mfd: devicetree: add bindings for Atmel Flexcom

2015-07-22 Thread Cyrille Pitchen
Le 21/07/2015 17:10, Lee Jones a écrit :
 On Tue, 21 Jul 2015, Cyrille Pitchen wrote:
 
 Hi Lee,

 Le 21/07/2015 11:09, Lee Jones a écrit :
 On Mon, 22 Jun 2015, Cyrille Pitchen wrote:
 ...
 +- atmel,flexcom-mode: shall be a string among { spi, usart, i2c, 
 twi }.
 +  i2c and twi are synonymous.

 Please use a numerical value instead.  You can then define it in
 include/dt-bindings/*

 This is only required if you supply more than one child node.  Is that
 the plan?  I ask because you only have one child node in the example
 below.

 The atmel,flexcom-mode property is always required. The reset value of the
 Operating Mode bit field inside the Flexcom Mode Register is 0 for no serial
 device. So none of the 3 embedded serial devices is clocked and all of their
 registers are inaccessible (read as zero).
 Before using any of the 3 serial devices, the Operating Mode must be set
 accordingly by updating the Mode Register. Once done, only the selected 
 serial
 device is clocked. Also the external I/O lines of the Flexcom are muxed to
 reach the selected serial device.

 The muxing is given by the following table:

 Flexcom pinUSART pinSPI pinI2C pin
 IO0  TXD   MOSITWD
 IO1  RXD   MISO   TWCK
 IO2  SCK   SPCK  -
 IO3  CTS  NPCS0  - 
 IO4  RTS  NPCS1  -


 Bus conflicting configuration:
  __
 |   Flexcom|
 |  _ _ _   |
 | | |__CLK__| SPI |__I/O__| |  |___   ___
 | | |   |_|   | |  |   | SPI Slave | | I2C Slave |
 | | CLK | | I/O |  |   |___| |___|
 |_| MUX |_| MUX |__|_||
 | | |__CLK__| I2C |__I/O__| |  | shared bus
 | |_|   |_|   |_|  |
 |__|


 For instance, it is very unlikely to connect both I2C and SPI slaves to
 the very same Flexcom because I/O lines are shared. The operating mode is
 selected once for all during the boot and will never change during runtime.
 That's why the Flexcom DT node should have exactly one child.
 
 You have contradicted your self here.  Firstly you say that the
 atmel,flexcom-mode property is always required, then you say that
 the DT node should only ever have one child.  If the latter is true,
 then you can infer which mode Flexcom needs to be in by which node is
 present.
 
OK, you're right. So on the next series (v6), I will simply remove the
atmel,flexcom-mode property from the DT bindings. Then, the driver will
look for the first available child node which compatible property contains
one of the substrings -usart, -spi or -i2c, setting the Flexcom operating
mode accordingly. This child node should be unique.

 +Example:
 +
 +flx0: flexcom@f8034000 {

 What references this node?  If nothing, then you can remove the label.
 OK, I will remove the label in the next series.

 +  compatible = atmel,sama5d2-flexcom;
 +  reg = 0xf8034000 0x200;
 +  clocks = flx0_clk;
 +  #address-cells = 1;
 +  #size-cells = 1;
 +  ranges = 0x0 0xf8034000 0x800;
 +  atmel,flexcom-mode = spi;
 +
 +  spi@f8034400 {
 +  compatible = atmel,at91rm9200-spi;
 +  reg = 0x400 0x200;
 +  interrupts = 19 IRQ_TYPE_LEVEL_HIGH 7;
 +  pinctrl-names = default;
 +  pinctrl-0 = pinctrl_flx0_ioset1;
 +  #address-cells = 1;
 +  #size-cells = 0;
 +  clocks = flx0_clk;
 +  clock-names = spi_clk;
 +  atmel,fifo-size = 32;
 +
 +  mtd_dataflash@0 {
 +  compatible = atmel,at25f512b;
 +  reg = 0;
 +  spi-max-frequency = 2000;
 +  };
 +  };
 +};


 Thanks for your review :)

 Best Regards,

 Cyrille
 

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


[PATCH v6 0/2] mfd: flexcom: add a driver for Flexcom

2015-07-22 Thread Cyrille Pitchen
ChangeLog

v6:
- select the operating mode according to the compatible DT property of
  the first available child node (should be unique).
- remove the atmel,flexcom-mode DT property so the need of a header file
  defining macros for the possible values of this deprecated property.

v5:
- create a header file containing macros used by DT bindings
- use numeric constants instead of strings to select the Flexcom mode
- change the license to GPL v2
- update the DT binding documentation to make it more readable and add
  references to USART, SPI and I2C DT binding documentations. remove the
  useless label in the Example section.
- change the register prefix from FX_ to FLEX_ to match the Flexcom
  programmer datasheet.
- rename some variables to make them more understandable.

v4:
- check clk_prepare_enable() return code in atmel_flexcom_probe()
- add a commit message to the DT binding patch

v3:
- remove MODULE_ALIAS()
- add Acked-by from Boris Brezillon and Alexandre Belloni

v2:
- enhance the documentation of DT bindings and change the way the ranges
  property is used.
- replace __raw_readl() and __raw_writel() by readl() and writel().
- change the module license to GPL for v2 or later
- print the selected flexcom mode after the hardware version

v1:
This series of patches a support to the Atmel Flexcom, a wrapper which
integrates an USART, a SPI controller and a TWI controller. Only one
peripheral can be used at a time. The active function is selected though
the Flexcom Mode Register.

Cyrille Pitchen (2):
  mfd: devicetree: add bindings for Atmel Flexcom
  mfd: atmel-flexcom: add a driver for Atmel Flexible Serial
Communication Unit

 .../devicetree/bindings/mfd/atmel-flexcom.txt  |  67 +++
 drivers/mfd/Kconfig|  11 ++
 drivers/mfd/Makefile   |   1 +
 drivers/mfd/atmel-flexcom.c| 126 +
 4 files changed, 205 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
 create mode 100644 drivers/mfd/atmel-flexcom.c

-- 
1.8.2.2

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


[PATCH v6 2/2] mfd: atmel-flexcom: add a driver for Atmel Flexible Serial Communication Unit

2015-07-22 Thread Cyrille Pitchen
This driver supports the new Atmel Flexcom. The Flexcom is a wrapper which
integrates one SPI controller, one I2C controller and one USART. Only one
function can be enabled at a time. This driver selects the function once
for all, when the Flexcom is probed, finding the first (should be unique)
available DT child node which compatible property contains one of the
following strings:
- -usart
- -spi
- -i2c

This driver has chosen to present the Flexcom to the system as a MFD so
the implementation is seamless for the existing Atmel SPI, I2C and USART
drivers.

Also the Flexcom embeds FIFOs: the latest patches of the SPI, I2C and
USART drivers take advantage of this new feature.

Signed-off-by: Cyrille Pitchen cyrille.pitc...@atmel.com
---
 drivers/mfd/Kconfig |  11 
 drivers/mfd/Makefile|   1 +
 drivers/mfd/atmel-flexcom.c | 126 
 3 files changed, 138 insertions(+)
 create mode 100644 drivers/mfd/atmel-flexcom.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index d5ad04dad081..9b33ad0653d1 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -59,6 +59,17 @@ config MFD_AAT2870_CORE
  additional drivers must be enabled in order to use the
  functionality of the device.
 
+config MFD_ATMEL_FLEXCOM
+   tristate Atmel Flexcom (Flexible Serial Communication Unit)
+   select MFD_CORE
+   depends on OF
+   help
+ Select this to get support for Atmel Flexcom. This is a wrapper
+ which embeds a SPI controller, a I2C controller and a USART. Only
+ one function can be used at a time. The choice is done at boot time
+ by the probe function of this MFD driver according to a device tree
+ property.
+
 config MFD_ATMEL_HLCDC
tristate Atmel HLCDC (High-end LCD Controller)
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 0e5cfeba107c..c666bf51abf3 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -160,6 +160,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
 obj-$(CONFIG_TPS65911_COMPARATOR)  += tps65911-comparator.o
 obj-$(CONFIG_MFD_TPS65090) += tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
+obj-$(CONFIG_MFD_ATMEL_FLEXCOM)+= atmel-flexcom.o
 obj-$(CONFIG_MFD_ATMEL_HLCDC)  += atmel-hlcdc.o
 obj-$(CONFIG_MFD_INTEL_MSIC)   += intel_msic.o
 obj-$(CONFIG_MFD_PALMAS)   += palmas.o
diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
new file mode 100644
index ..8ba1862fbb74
--- /dev/null
+++ b/drivers/mfd/atmel-flexcom.c
@@ -0,0 +1,126 @@
+/*
+ * Driver for Atmel Flexcom
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen cyrille.pitc...@atmel.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see http://www.gnu.org/licenses/.
+ */
+
+#include linux/module.h
+#include linux/types.h
+#include linux/kernel.h
+#include linux/platform_device.h
+#include linux/of.h
+#include linux/of_platform.h
+#include linux/err.h
+#include linux/io.h
+#include linux/clk.h
+
+/* I/O register offsets */
+#define FLEX_MR0x0 /* Mode Register */
+#define FLEX_VERSION   0xfc/* Version Register */
+
+/* Mode Register bit fields */
+#define FLEX_MR_OPMODE_MASK0x3
+#define FLEX_MR_OPMODE_NO_COM  0x0
+#define FLEX_MR_OPMODE_USART   0x1
+#define FLEX_MR_OPMODE_SPI 0x2
+#define FLEX_MR_OPMODE_TWI 0x3
+
+
+static int atmel_flexcom_probe(struct platform_device *pdev)
+{
+   struct device_node *child, *np = pdev-dev.of_node;
+   struct clk *clk;
+   struct resource *res;
+   void __iomem *base;
+   u32 opmode = FLEX_MR_OPMODE_NO_COM;
+   int err;
+
+   for_each_child_of_node(np, child) {
+   const char *compatible;
+   int cplen;
+
+   if (!of_device_is_available(child))
+   continue;
+
+   compatible = of_get_property(child, compatible, cplen);
+   if (!compatible || strlen(compatible)  cplen)
+   continue;
+
+   if (strstr(compatible, -usart)) {
+   opmode = FLEX_MR_OPMODE_USART;
+   break;
+   }
+
+   if (strstr(compatible, -spi)) {
+   opmode = FLEX_MR_OPMODE_SPI;
+   break;
+   }
+
+   if (strstr(compatible, -i2c)) {
+   opmode

  1   2   3   >