[PATCHv3] spi: orion: Add multiple chip select support to spi-orion

2015-01-15 Thread Ken Wilson
This commit adds support for multiple hardware chip selects to spi-orion.
Different SoCs support different number of chip selects (up to
8 on some platforms). The driver allows up to this number, and it is up
to the implementer to only use the chip selects that are available.

Signed-off-by: Ken Wilson 
---
 drivers/spi/spi-orion.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index e6ac9d5..db50f0e 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -28,7 +28,12 @@
 /* Runtime PM autosuspend timeout: PM is fairly light on this driver */
 #define SPI_AUTOSUSPEND_TIMEOUT200
 
-#define ORION_NUM_CHIPSELECTS  1 /* only one slave is supported*/
+/* Some SoCs using this driver support up to 8 chip selects.
+ * It is up to the implementer to only use the chip selects
+ * that are available.
+ */
+#define ORION_NUM_CHIPSELECTS  8
+
 #define ORION_SPI_WAIT_RDY_MAX_LOOP2000 /* in usec */
 
 #define ORION_SPI_IF_CTRL_REG  0x00
@@ -44,6 +49,10 @@
 #define ARMADA_SPI_CLK_PRESCALE_MASK   0xDF
 #define ORION_SPI_MODE_MASK(ORION_SPI_MODE_CPOL | \
 ORION_SPI_MODE_CPHA)
+#define ORION_SPI_CS_MASK  0x1C
+#define ORION_SPI_CS_SHIFT 2
+#define ORION_SPI_CS(cs)   ((cs << ORION_SPI_CS_SHIFT) & \
+   ORION_SPI_CS_MASK)
 
 enum orion_spi_type {
ORION_SPI,
@@ -221,6 +230,10 @@ static void orion_spi_set_cs(struct spi_device *spi, bool 
enable)
 
orion_spi = spi_master_get_devdata(spi->master);
 
+   orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK);
+   orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG,
+   ORION_SPI_CS(spi->chip_select));
+
/* Chip select logic is inverted from spi_set_cs */
if (!enable)
orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
-- 
2.0.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCHv2 2/2] spi: orion: Add multiple chip select support to spi-orion

2015-01-14 Thread Ken Wilson


On 15/01/15 06:06, Mark Brown wrote:

On Mon, Jan 12, 2015 at 01:14:00PM +1000, Ken Wilson wrote:


+- num-cs : The total number of chip selects used by this platform.
+   If unset, this defaults to 1.

So, this is intended to be the number of hardware chip selects that can
be configured but the first commit mentioned GPIOs as an option too so
we should at least say that this is specifically the controller
supported ones.  However...


+#define ORION_SPI_CS_MASK  0x1C
+#define ORION_SPI_CS_SHIFT 2
+#define ORION_SPI_CS(cs)   ((cs << ORION_SPI_CS_SHIFT) & \
+   ORION_SPI_CS_MASK)

...given that we have a fixed bitfield here which we know and doesn't
appear to depend on configuration do we even need this to be
configurable - given that we're going to need an explicit node for any
slave can't we just accept any sane chip select for a slave without
extending the binding?
The different implementations that use this driver (Marvell Kirkwood, 
Armada 370/375) all
have a different number of supported chip selects, that fit into this 
bit mask. There are also
multiple SPI controllers on each SoC which support different numbers of 
chip selects.
For example, on the Armada 375, SPI0 supports 3 chip selects, while SPI1 
only has 1.


I agree that we could support any sane chip select for a slave, since 
the slave addresses do need

to be explicitly defined. I'm happy with whatever your preference is.

Thanks,
Ken
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCHv2 2/2] spi: orion: Add multiple chip select support to spi-orion

2015-01-11 Thread Ken Wilson
This commit adds support for multiple hardware chip selects to spi-orion.
The number of supported chip selects varies based on the SoC and pin
configuration, so it is set using the num-cs device tree binding.

Signed-off-by: Ken Wilson 
---
 Documentation/devicetree/bindings/spi/spi-orion.txt |  3 +++
 drivers/spi/spi-orion.c | 17 +++--
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-orion.txt 
b/Documentation/devicetree/bindings/spi/spi-orion.txt
index 50c3a3d..0f8fd7e 100644
--- a/Documentation/devicetree/bindings/spi/spi-orion.txt
+++ b/Documentation/devicetree/bindings/spi/spi-orion.txt
@@ -6,6 +6,8 @@ Required properties:
 - cell-index : Which of multiple SPI controllers is this.
 Optional properties:
 - interrupts : Is currently not used.
+- num-cs : The total number of chip selects used by this platform.
+   If unset, this defaults to 1.
 
 Example:
spi@10600 {
@@ -15,5 +17,6 @@ Example:
   cell-index = <0>;
   reg = <0x10600 0x28>;
   interrupts = <23>;
+  num-cs = <1>;
   status = "disabled";
};
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index e6ac9d5..1c28152 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -28,7 +28,6 @@
 /* Runtime PM autosuspend timeout: PM is fairly light on this driver */
 #define SPI_AUTOSUSPEND_TIMEOUT200
 
-#define ORION_NUM_CHIPSELECTS  1 /* only one slave is supported*/
 #define ORION_SPI_WAIT_RDY_MAX_LOOP2000 /* in usec */
 
 #define ORION_SPI_IF_CTRL_REG  0x00
@@ -44,6 +43,10 @@
 #define ARMADA_SPI_CLK_PRESCALE_MASK   0xDF
 #define ORION_SPI_MODE_MASK(ORION_SPI_MODE_CPOL | \
 ORION_SPI_MODE_CPHA)
+#define ORION_SPI_CS_MASK  0x1C
+#define ORION_SPI_CS_SHIFT 2
+#define ORION_SPI_CS(cs)   ((cs << ORION_SPI_CS_SHIFT) & \
+   ORION_SPI_CS_MASK)
 
 enum orion_spi_type {
ORION_SPI,
@@ -221,6 +224,10 @@ static void orion_spi_set_cs(struct spi_device *spi, bool 
enable)
 
orion_spi = spi_master_get_devdata(spi->master);
 
+   orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK);
+   orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG,
+   ORION_SPI_CS(spi->chip_select));
+
/* Chip select logic is inverted from spi_set_cs */
if (!enable)
orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
@@ -406,17 +413,23 @@ static int orion_spi_probe(struct platform_device *pdev)
master->bus_num = pdev->id;
if (pdev->dev.of_node) {
u32 cell_index;
+   u32 num_cs;
 
if (!of_property_read_u32(pdev->dev.of_node, "cell-index",
  &cell_index))
master->bus_num = cell_index;
+
+   if (!of_property_read_u32(pdev->dev.of_node, "num_cs",
+ &num_cs))
+   master->num_chipselect = num_cs;
+   else
+   master->num_chipselect = 1;
}
 
/* we support only mode 0, and no options */
master->mode_bits = SPI_CPHA | SPI_CPOL;
master->set_cs = orion_spi_set_cs;
master->transfer_one = orion_spi_transfer_one;
-   master->num_chipselect = ORION_NUM_CHIPSELECTS;
master->setup = orion_spi_setup;
master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
master->auto_runtime_pm = true;
-- 
2.0.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCHv2 0/2] spi: orion: Add multiple chip select support to spi-orion

2015-01-11 Thread Ken Wilson
Hello,  

This patch series adds multiple chip select support for the spi-orion driver.
The first patch moves spi-orion to use the spi setup/set_cs/transfer_one
 
function pointers, which reduces duplicated code, and simplifies the chip 
select support implementation.

The second patch adds support for multiple chip selects. Currently
there is no additional support for gpio chip selects, as I do not 
have a board to test that with. 

These patches have been tested on an Armada 375 with 2 SPI-NOR chips.

Thanks,
Ken

Ken Wilson (2):
  spi: orion: Change spi-orion to use transfer_one() semantics for SPI
transfers
  spi: orion: Add multiple chip select support to spi-orion

 .../devicetree/bindings/spi/spi-orion.txt  |  3 +
 drivers/spi/spi-orion.c| 90 +-
 2 files changed, 41 insertions(+), 52 deletions(-)

-- 
2.0.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCHv2 1/2] spi: orion: Change spi-orion to use transfer_one() semantics for SPI transfers

2015-01-11 Thread Ken Wilson
This commit changes spi-orion to provide setup, set_cs, and transfer_one
functions instead of transfer_one_message. This allows chip select support
for both native and GPIO chip selects to be added.

Signed-off-by: Ken Wilson 
---
 drivers/spi/spi-orion.c | 73 -
 1 file changed, 23 insertions(+), 50 deletions(-)

diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index c76b7d7..e6ac9d5 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -215,9 +215,14 @@ orion_spi_setup_transfer(struct spi_device *spi, struct 
spi_transfer *t)
return 0;
 }
 
-static void orion_spi_set_cs(struct orion_spi *orion_spi, int enable)
+static void orion_spi_set_cs(struct spi_device *spi, bool enable)
 {
-   if (enable)
+   struct orion_spi *orion_spi;
+
+   orion_spi = spi_master_get_devdata(spi->master);
+
+   /* Chip select logic is inverted from spi_set_cs */
+   if (!enable)
orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
else
orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
@@ -332,64 +337,31 @@ out:
return xfer->len - count;
 }
 
-static int orion_spi_transfer_one_message(struct spi_master *master,
-  struct spi_message *m)
+static int orion_spi_transfer_one(struct spi_master *master,
+   struct spi_device *spi,
+   struct spi_transfer *t)
 {
-   struct orion_spi *orion_spi = spi_master_get_devdata(master);
-   struct spi_device *spi = m->spi;
-   struct spi_transfer *t = NULL;
-   int par_override = 0;
int status = 0;
-   int cs_active = 0;
-
-   /* Load defaults */
-   status = orion_spi_setup_transfer(spi, NULL);
 
+   status = orion_spi_setup_transfer(spi, t);
if (status < 0)
-   goto msg_done;
-
-   list_for_each_entry(t, &m->transfers, transfer_list) {
-   if (par_override || t->speed_hz || t->bits_per_word) {
-   par_override = 1;
-   status = orion_spi_setup_transfer(spi, t);
-   if (status < 0)
-   break;
-   if (!t->speed_hz && !t->bits_per_word)
-   par_override = 0;
-   }
-
-   if (!cs_active) {
-   orion_spi_set_cs(orion_spi, 1);
-   cs_active = 1;
-   }
+   return status;
 
-   if (t->len)
-   m->actual_length += orion_spi_write_read(spi, t);
+   if (t->len)
+   orion_spi_write_read(spi, t);
 
-   if (t->delay_usecs)
-   udelay(t->delay_usecs);
-
-   if (t->cs_change) {
-   orion_spi_set_cs(orion_spi, 0);
-   cs_active = 0;
-   }
-   }
-
-msg_done:
-   if (cs_active)
-   orion_spi_set_cs(orion_spi, 0);
-
-   m->status = status;
-   spi_finalize_current_message(master);
+   return status;
+}
 
-   return 0;
+static int orion_spi_setup(struct spi_device *spi)
+{
+   return orion_spi_setup_transfer(spi, NULL);
 }
 
 static int orion_spi_reset(struct orion_spi *orion_spi)
 {
/* Verify that the CS is deasserted */
-   orion_spi_set_cs(orion_spi, 0);
-
+   orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
return 0;
 }
 
@@ -442,9 +414,10 @@ static int orion_spi_probe(struct platform_device *pdev)
 
/* we support only mode 0, and no options */
master->mode_bits = SPI_CPHA | SPI_CPOL;
-
-   master->transfer_one_message = orion_spi_transfer_one_message;
+   master->set_cs = orion_spi_set_cs;
+   master->transfer_one = orion_spi_transfer_one;
master->num_chipselect = ORION_NUM_CHIPSELECTS;
+   master->setup = orion_spi_setup;
master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
master->auto_runtime_pm = true;
 
-- 
2.0.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] spi: orion: Add multiple chip select support for Armada 370 and 375

2015-01-07 Thread Ken Wilson
Hi Thomas,
> On 7 Jan 2015, at 4:41 pm, Thomas Petazzoni 
>  wrote:
> 
> Dear Gregory CLEMENT,
> 
> On Tue, 06 Jan 2015 23:00:54 +0100, Gregory CLEMENT wrote:
> 
>> On 06/01/2015 22:30, Ken Wilson wrote:
>>> Create a new dt binding for the Armada 375 that supports up to
>>> 3 chip selects but uses the same prescaler values and algorithm
>>> as the basic orion binding.
>> 
>> There was already a patch that have been sent for this:
>> http://thread.gmane.org/gmane.linux.kernel.spi.devel/17808/focus=17809
>> 
>> but in the end it has not been merged. The last email on the thread was
>> about doing the manipulation in set_cs and not in setup_transfer(). And I
>> didn't find a newer version.
>> 
>> Maybe it just fell through the cracks.
>> Thomas did you remember of it?
> 
> Yes, it is still on my TODO-list, but I haven't yet gotten around to
> submitting a new version. So I haven't looked at Ken's contribution,
> but if Ken is willing to bring it up to a state where it can be
> mainlined, that would definitely be welcome.

I’m happy to do that

Thanks,
Ken

> 
> Thanks,
> 
> Thomas
> -- 
> Thomas Petazzoni, CTO, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com
> 
> ___
> linux-arm-kernel mailing list
> linux-arm-ker...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] spi: orion: Add multiple chip select support for Armada 370 and 375

2015-01-06 Thread Ken Wilson
Create a new dt binding for the Armada 375 that supports up to
3 chip selects but uses the same prescaler values and algorithm
as the basic orion binding.

Update the Armada 370 so that it supports up to 4 chip selects.

This has been tested on the Armada 375 with multiple SPI-NOR chips.

Signed-off-by: Ken Wilson 
---
 .../devicetree/bindings/spi/spi-orion.txt  |  3 ++-
 arch/arm/boot/dts/armada-375.dtsi  |  4 +--
 drivers/spi/spi-orion.c| 29 +++---
 3 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-orion.txt 
b/Documentation/devicetree/bindings/spi/spi-orion.txt
index 50c3a3d..2aeeb85 100644
--- a/Documentation/devicetree/bindings/spi/spi-orion.txt
+++ b/Documentation/devicetree/bindings/spi/spi-orion.txt
@@ -1,7 +1,8 @@
 Marvell Orion SPI device
 
 Required properties:
-- compatible : should be "marvell,orion-spi" or "marvell,armada-370-spi".
+- compatible : should be "marvell,orion-spi", "marvell,armada-370-spi",
+   or "marvell,armada-375-spi".
 - reg : offset and length of the register set for the device
 - cell-index : Which of multiple SPI controllers is this.
 Optional properties:
diff --git a/arch/arm/boot/dts/armada-375.dtsi 
b/arch/arm/boot/dts/armada-375.dtsi
index de65714..f7a5ce2 100644
--- a/arch/arm/boot/dts/armada-375.dtsi
+++ b/arch/arm/boot/dts/armada-375.dtsi
@@ -192,7 +192,7 @@
};
 
spi0: spi@10600 {
-   compatible = "marvell,orion-spi";
+   compatible = "marvell,armada-375-spi", 
"marvell,orion-spi";
reg = <0x10600 0x50>;
#address-cells = <1>;
#size-cells = <0>;
@@ -203,7 +203,7 @@
};
 
spi1: spi@10680 {
-   compatible = "marvell,orion-spi";
+   compatible = "marvell,armada-375-spi", 
"marvell,orion-spi";
reg = <0x10680 0x50>;
#address-cells = <1>;
#size-cells = <0>;
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index c76b7d7..4129c37 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -28,7 +28,6 @@
 /* Runtime PM autosuspend timeout: PM is fairly light on this driver */
 #define SPI_AUTOSUSPEND_TIMEOUT200
 
-#define ORION_NUM_CHIPSELECTS  1 /* only one slave is supported*/
 #define ORION_SPI_WAIT_RDY_MAX_LOOP2000 /* in usec */
 
 #define ORION_SPI_IF_CTRL_REG  0x00
@@ -44,6 +43,7 @@
 #define ARMADA_SPI_CLK_PRESCALE_MASK   0xDF
 #define ORION_SPI_MODE_MASK(ORION_SPI_MODE_CPOL | \
 ORION_SPI_MODE_CPHA)
+#define ORION_SPI_CS_MASK  0x1C
 
 enum orion_spi_type {
ORION_SPI,
@@ -55,6 +55,7 @@ struct orion_spi_dev {
unsigned intmin_divisor;
unsigned intmax_divisor;
u32 prescale_mask;
+   u8  num_cs;
 };
 
 struct orion_spi {
@@ -201,6 +202,13 @@ orion_spi_setup_transfer(struct spi_device *spi, struct 
spi_transfer *t)
 
orion_spi_mode_set(spi);
 
+   if (orion_spi->master->num_chipselect > 1) {
+   orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG,
+   ORION_SPI_CS_MASK);
+   orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG,
+   (spi->chip_select) << 2);
+   }
+
rc = orion_spi_baudrate_set(spi, speed);
if (rc)
return rc;
@@ -398,18 +406,31 @@ static const struct orion_spi_dev orion_spi_dev_data = {
.min_divisor = 4,
.max_divisor = 30,
.prescale_mask = ORION_SPI_CLK_PRESCALE_MASK,
+   .num_cs = 1,
 };
 
-static const struct orion_spi_dev armada_spi_dev_data = {
+static const struct orion_spi_dev armada_370_spi_dev_data = {
.typ = ARMADA_SPI,
.min_divisor = 1,
.max_divisor = 1920,
.prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK,
+   .num_cs = 4,
+};
+
+static const struct orion_spi_dev armada_375_spi_dev_data = {
+   .typ = ORION_SPI,
+   .min_divisor = 4,
+   .max_divisor = 30,
+   .prescale_mask = ORION_SPI_CLK_PRESCALE_MASK,
+   .num_cs = 3,
 };
 
 static const struct of_device_id orion_spi_of_match_table[] = {
{ .compatible = "marvell,orion-spi", .data = &orion_spi_dev_data, },
-   { .compatible = "marvell,armada-370-spi", .data = &armada_spi_dev_data, 
},
+   { .compatible = "marvell,armada-370-spi",
+   .d