spi: pl022: Add support for chip select extension
diff mbox

Message ID 1410360030-26634-1-git-send-email-anders.berg@avagotech.com
State New, archived
Headers show

Commit Message

Anders Berg Sept. 10, 2014, 2:40 p.m. UTC
Add support for a extended PL022 which has an extra register for controlling up
to five chip select signals. This controller is found on the AXM5516 SoC.
Unfortunately the PrimeCell identification registers are identical to a
standard ARM PL022. To work around this, the peripheral ID must be overridden
in the device tree using the "arm,primecell-periphid" property with the value
0x000b6022.

Signed-off-by: Anders Berg <anders.berg@avagotech.com>
---
 drivers/spi/spi-pl022.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 58 insertions(+), 1 deletion(-)

Comments

Linus Walleij Sept. 11, 2014, 1:26 p.m. UTC | #1
On Wed, Sep 10, 2014 at 4:40 PM, Anders Berg <anders.berg@avagotech.com> wrote:

> Add support for a extended PL022 which has an extra register for controlling up
> to five chip select signals. This controller is found on the AXM5516 SoC.
> Unfortunately the PrimeCell identification registers are identical to a
> standard ARM PL022. To work around this, the peripheral ID must be overridden
> in the device tree using the "arm,primecell-periphid" property with the value
> 0x000b6022.
>
> Signed-off-by: Anders Berg <anders.berg@avagotech.com>
(...)
> +               /*
> +                * PL022 variant that has a chip select control register whih
> +                * allows control of 5 output signals nCS[0:4].
> +                */
> +               .id     = 0x000b6022,

OK so you're defining 0xb6 to the the 8bit ID for LSI.

Do you have some special reason for this, like that it appears
in some other silicon block from LSI? Otherwise I suggest using
0x4c (uppercase 'L') so as to follow the pattern of the other
vendor IDs.

Please patch include/linux/amba/bus.h to add
AMBA_VENDOR_LSI = 0x4c (or 6b) as well, as this is the first
occurence.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Anders Berg Sept. 11, 2014, 9:29 p.m. UTC | #2
On Thu, Sep 11, 2014 at 3:26 PM, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Wed, Sep 10, 2014 at 4:40 PM, Anders Berg <anders.berg@avagotech.com> wrote:
>
>> Add support for a extended PL022 which has an extra register for controlling up
>> to five chip select signals. This controller is found on the AXM5516 SoC.
>> Unfortunately the PrimeCell identification registers are identical to a
>> standard ARM PL022. To work around this, the peripheral ID must be overridden
>> in the device tree using the "arm,primecell-periphid" property with the value
>> 0x000b6022.
>>
>> Signed-off-by: Anders Berg <anders.berg@avagotech.com>
> (...)
>> +               /*
>> +                * PL022 variant that has a chip select control register whih
>> +                * allows control of 5 output signals nCS[0:4].
>> +                */
>> +               .id     = 0x000b6022,
>
> OK so you're defining 0xb6 to the the 8bit ID for LSI.
>
> Do you have some special reason for this, like that it appears
> in some other silicon block from LSI? Otherwise I suggest using
> 0x4c (uppercase 'L') so as to follow the pattern of the other
> vendor IDs.

I picked 0xb6 since I've seen some reference manuals for other AMBA
peripherals the use of JEDEC assigned vendor IDs in this register
field (see the PL390 TRM for example). So I put the LSI Logic 7-bit
JEDEC ID (0x36) there: [0:6] = 0x36, [7] = 1 (the MSB set to '1' to
signify the use of JEDEC ID instead of a "classic" AMBA vendor).

/Anders
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Linus Walleij Sept. 12, 2014, 5 p.m. UTC | #3
On Thu, Sep 11, 2014 at 10:10 PM, Anders Berg <anders.berg@avagotech.com> wrote:
> On Thu, Sep 11, 2014 at 3:26 PM, Linus Walleij <linus.walleij@linaro.org>
> wrote:
>> On Wed, Sep 10, 2014 at 4:40 PM, Anders Berg <anders.berg@avagotech.com>
>> wrote:
>> (...)
>> > +               /*
>> > +                * PL022 variant that has a chip select control register
>> > whih
>> > +                * allows control of 5 output signals nCS[0:4].
>> > +                */
>> > +               .id     = 0x000b6022,
>>
>> OK so you're defining 0xb6 to the the 8bit ID for LSI.
>>
>> Do you have some special reason for this, like that it appears
>> in some other silicon block from LSI? Otherwise I suggest using
>> 0x4c (uppercase 'L') so as to follow the pattern of the other
>> vendor IDs.
>
>
> I picked 0xb6 since I've seen some reference manuals for other AMBA
> peripherals the use of JEDEC assigned vendor IDs in this register field (see
> the PL390 TRM for example). So I put the LSI Logic 7-bit JEDEC ID (0x36)
> there: [0:6] = 0x36, [7] = 1 (the MSB set to '1' to signify the use of JEDEC
> ID instead of a "classic" AMBA vendor).

Hey that's very observant, I had no clue about that scheme!

Can you write a comment about this in <linux/amba/bus.h> when
you patch it (like above the enum) so we know that in the future
when people need to pick new IDs?

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Anders Berg Sept. 15, 2014, 10:59 a.m. UTC | #4
On Fri, Sep 12, 2014 at 7:00 PM, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Thu, Sep 11, 2014 at 10:10 PM, Anders Berg <anders.berg@avagotech.com> wrote:
(...)
>> I picked 0xb6 since I've seen some reference manuals for other AMBA
>> peripherals the use of JEDEC assigned vendor IDs in this register field (see
>> the PL390 TRM for example). So I put the LSI Logic 7-bit JEDEC ID (0x36)
>> there: [0:6] = 0x36, [7] = 1 (the MSB set to '1' to signify the use of JEDEC
>> ID instead of a "classic" AMBA vendor).
>
> Hey that's very observant, I had no clue about that scheme!
>
> Can you write a comment about this in <linux/amba/bus.h> when
> you patch it (like above the enum) so we know that in the future
> when people need to pick new IDs?

Sure, will do.

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

Patch
diff mbox

diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 1189cfd..b395489 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -82,6 +82,7 @@ 
 #define SSP_MIS(r)	(r + 0x01C)
 #define SSP_ICR(r)	(r + 0x020)
 #define SSP_DMACR(r)	(r + 0x024)
+#define SSP_CSR(r)	(r + 0x030) /* vendor extension */
 #define SSP_ITCR(r)	(r + 0x080)
 #define SSP_ITIP(r)	(r + 0x084)
 #define SSP_ITOP(r)	(r + 0x088)
@@ -198,6 +199,12 @@ 
 #define SSP_DMACR_MASK_TXDMAE		(0x1UL << 1)
 
 /*
+ * SSP Chip Select Control Register - SSP_CSR
+ * (vendor extension)
+ */
+#define SSP_CSR_CSVALUE_MASK		(0x1FUL << 0)
+
+/*
  * SSP Integration Test control Register - SSP_ITCR
  */
 #define SSP_ITCR_MASK_ITEN		(0x1UL << 0)
@@ -313,6 +320,7 @@  enum ssp_writing {
  * @extended_cr: 32 bit wide control register 0 with extra
  * features and extra features in CR1 as found in the ST variants
  * @pl023: supports a subset of the ST extensions called "PL023"
+ * @internal_cs_ctrl: supports chip select control register
  */
 struct vendor_data {
 	int fifodepth;
@@ -321,6 +329,7 @@  struct vendor_data {
 	bool extended_cr;
 	bool pl023;
 	bool loopback;
+	bool internal_cs_ctrl;
 };
 
 /**
@@ -440,9 +449,32 @@  static void null_cs_control(u32 command)
 	pr_debug("pl022: dummy chip select control, CS=0x%x\n", command);
 }
 
+/**
+ * internal_cs_control - Control chip select signals via SSP_CSR.
+ * @pl022: SSP driver private data structure
+ * @command: select/delect the chip
+ *
+ * Used on controller with internal chip select control via SSP_CSR register
+ * (vendor extension). Each of the 5 LSB in the register controls one chip
+ * select signal.
+ */
+static void internal_cs_control(struct pl022 *pl022, u32 command)
+{
+	u32 tmp;
+
+	tmp = readw(SSP_CSR(pl022->virtbase));
+	if (command == SSP_CHIP_SELECT)
+		tmp &= ~BIT(pl022->cur_cs);
+	else
+		tmp |= BIT(pl022->cur_cs);
+	writew(tmp, SSP_CSR(pl022->virtbase));
+}
+
 static void pl022_cs_control(struct pl022 *pl022, u32 command)
 {
-	if (gpio_is_valid(pl022->cur_cs))
+	if (pl022->vendor->internal_cs_ctrl)
+		internal_cs_control(pl022, command);
+	else if (gpio_is_valid(pl022->cur_cs))
 		gpio_set_value(pl022->cur_cs, command);
 	else
 		pl022->cur_chip->cs_control(command);
@@ -2118,6 +2150,9 @@  static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	if (platform_info->num_chipselect && platform_info->chipselects) {
 		for (i = 0; i < num_cs; i++)
 			pl022->chipselects[i] = platform_info->chipselects[i];
+	} else if (pl022->vendor->internal_cs_ctrl) {
+		for (i = 0; i < num_cs; i++)
+			pl022->chipselects[i] = i;
 	} else if (IS_ENABLED(CONFIG_OF)) {
 		for (i = 0; i < num_cs; i++) {
 			int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
@@ -2347,6 +2382,7 @@  static struct vendor_data vendor_arm = {
 	.extended_cr = false,
 	.pl023 = false,
 	.loopback = true,
+	.internal_cs_ctrl = false,
 };
 
 static struct vendor_data vendor_st = {
@@ -2356,6 +2392,7 @@  static struct vendor_data vendor_st = {
 	.extended_cr = true,
 	.pl023 = false,
 	.loopback = true,
+	.internal_cs_ctrl = false,
 };
 
 static struct vendor_data vendor_st_pl023 = {
@@ -2365,6 +2402,17 @@  static struct vendor_data vendor_st_pl023 = {
 	.extended_cr = true,
 	.pl023 = true,
 	.loopback = false,
+	.internal_cs_ctrl = false,
+};
+
+static struct vendor_data vendor_lsi = {
+	.fifodepth = 8,
+	.max_bpw = 16,
+	.unidir = false,
+	.extended_cr = false,
+	.pl023 = false,
+	.loopback = true,
+	.internal_cs_ctrl = true,
 };
 
 static struct amba_id pl022_ids[] = {
@@ -2398,6 +2446,15 @@  static struct amba_id pl022_ids[] = {
 		.mask	= 0xffffffff,
 		.data	= &vendor_st_pl023,
 	},
+	{
+		/*
+		 * PL022 variant that has a chip select control register whih
+		 * allows control of 5 output signals nCS[0:4].
+		 */
+		.id	= 0x000b6022,
+		.mask	= 0x000fffff,
+		.data	= &vendor_lsi,
+	},
 	{ 0, 0 },
 };