All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v11] dm: at91: Add driver model support for the spi driver
@ 2016-10-28  6:17 Wenyou Yang
  2016-10-28 16:49 ` [U-Boot] [U-Boot, " Andreas Bießmann
  0 siblings, 1 reply; 4+ messages in thread
From: Wenyou Yang @ 2016-10-28  6:17 UTC (permalink / raw)
  To: u-boot

Add driver model support while retaining the existing legacy code.
This allows the driver to support boards that have converted to
driver model as well as those that have not.

Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Stephen Warren <swarren@nvidia.com>
---

Changes in v11:
 - Set cs_gpio direction to output and active.
 - Use wait_for_bit() to replace do {} while ().
 - Add more description for help of ATMEL_SPI.

Changes in v10:
 - Add Acked-by tag.

Changes in v9:
 - Due to the peripheral clock driver improvement, remove the
   unneccessary clock calling.

Changes in v8:
 - Fix compile error for AVR32.

Changes in v7:
 - Move gpio_request_list_by_name() to _probe(), remove
   *_ofdata_to_platdata().

Changes in v6:
 - Remove the two flash related options.

Changes in v5:
 - Change clk_client.h -> clk.h to adapt to clk API conversion.

Changes in v4:
 - Collect Reviewed-by tag.
 - Update the clk API based on [PATCH] clk: convert API to match
   reset/mailbox fstyle (http://patchwork.ozlabs.org/patch/625342/).
 - Remove check on dev_get_parent() return.
 - Fixed the return value, -ENODEV->-EINVAL.
 - Retain #include <asm/arch/clk.h> line.

Changes in v3:
 - Remove redundant log print.

Changes in v2:
 - Add clock support.

 drivers/spi/Kconfig     |   8 ++
 drivers/spi/atmel_spi.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 296 insertions(+)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 8724f87..0f51b3a 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -32,6 +32,14 @@ config ATH79_SPI
 	  uses driver model and requires a device tree binding to operate.
 	  please refer to doc/device-tree-bindings/spi/spi-ath79.txt.
 
+config ATMEL_SPI
+	bool "Atmel SPI driver"
+	depends on ARCH_AT91
+	help
+	  This enables driver for the Atmel SPI Controller, present on
+	  many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
+	  used to access the SPI Flash, such as AT25DF321.
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index ed6278b..7649114 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -4,16 +4,30 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 #include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <fdtdec.h>
 #include <spi.h>
 #include <malloc.h>
+#include <wait_bit.h>
 
 #include <asm/io.h>
 
 #include <asm/arch/clk.h>
 #include <asm/arch/hardware.h>
+#ifdef CONFIG_DM_SPI
+#include <asm/arch/at91_spi.h>
+#endif
+#ifdef CONFIG_DM_GPIO
+#include <asm/gpio.h>
+#endif
 
 #include "atmel_spi.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_DM_SPI
+
 static int spi_has_wdrbt(struct atmel_spi_slave *slave)
 {
 	unsigned int ver;
@@ -209,3 +223,277 @@ out:
 
 	return 0;
 }
+
+#else
+
+#define MAX_CS_COUNT	4
+
+struct atmel_spi_platdata {
+	struct at91_spi *regs;
+};
+
+struct atmel_spi_priv {
+	unsigned int freq;		/* Default frequency */
+	unsigned int mode;
+	ulong bus_clk_rate;
+	struct gpio_desc cs_gpios[MAX_CS_COUNT];
+};
+
+static int atmel_spi_claim_bus(struct udevice *dev)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus);
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+	struct at91_spi *reg_base = bus_plat->regs;
+	u32 cs = slave_plat->cs;
+	u32 freq = priv->freq;
+	u32 scbr, csrx, mode;
+
+	scbr = (priv->bus_clk_rate + freq - 1) / freq;
+	if (scbr > ATMEL_SPI_CSRx_SCBR_MAX)
+		return -EINVAL;
+
+	if (scbr < 1)
+		scbr = 1;
+
+	csrx = ATMEL_SPI_CSRx_SCBR(scbr);
+	csrx |= ATMEL_SPI_CSRx_BITS(ATMEL_SPI_BITS_8);
+
+	if (!(priv->mode & SPI_CPHA))
+		csrx |= ATMEL_SPI_CSRx_NCPHA;
+	if (priv->mode & SPI_CPOL)
+		csrx |= ATMEL_SPI_CSRx_CPOL;
+
+	writel(csrx, &reg_base->csr[cs]);
+
+	mode = ATMEL_SPI_MR_MSTR |
+	       ATMEL_SPI_MR_MODFDIS |
+	       ATMEL_SPI_MR_WDRBT |
+	       ATMEL_SPI_MR_PCS(~(1 << cs));
+
+	writel(mode, &reg_base->mr);
+
+	writel(ATMEL_SPI_CR_SPIEN, &reg_base->cr);
+
+	return 0;
+}
+
+static int atmel_spi_release_bus(struct udevice *dev)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus);
+
+	writel(ATMEL_SPI_CR_SPIDIS, &bus_plat->regs->cr);
+
+	return 0;
+}
+
+static void atmel_spi_cs_activate(struct udevice *dev)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+	u32 cs = slave_plat->cs;
+
+	dm_gpio_set_value(&priv->cs_gpios[cs], 0);
+}
+
+static void atmel_spi_cs_deactivate(struct udevice *dev)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+	u32 cs = slave_plat->cs;
+
+	dm_gpio_set_value(&priv->cs_gpios[cs], 1);
+}
+
+static int atmel_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			  const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus);
+	struct at91_spi *reg_base = bus_plat->regs;
+
+	u32 len_tx, len_rx, len;
+	u32 status;
+	const u8 *txp = dout;
+	u8 *rxp = din;
+	u8 value;
+
+	if (bitlen == 0)
+		goto out;
+
+	/*
+	 * The controller can do non-multiple-of-8 bit
+	 * transfers, but this driver currently doesn't support it.
+	 *
+	 * It's also not clear how such transfers are supposed to be
+	 * represented as a stream of bytes...this is a limitation of
+	 * the current SPI interface.
+	 */
+	if (bitlen % 8) {
+		/* Errors always terminate an ongoing transfer */
+		flags |= SPI_XFER_END;
+		goto out;
+	}
+
+	len = bitlen / 8;
+
+	/*
+	 * The controller can do automatic CS control, but it is
+	 * somewhat quirky, and it doesn't really buy us much anyway
+	 * in the context of U-Boot.
+	 */
+	if (flags & SPI_XFER_BEGIN) {
+		atmel_spi_cs_activate(dev);
+
+		/*
+		 * sometimes the RDR is not empty when we get here,
+		 * in theory that should not happen, but it DOES happen.
+		 * Read it here to be on the safe side.
+		 * That also clears the OVRES flag. Required if the
+		 * following loop exits due to OVRES!
+		 */
+		readl(&reg_base->rdr);
+	}
+
+	for (len_tx = 0, len_rx = 0; len_rx < len; ) {
+		status = readl(&reg_base->sr);
+
+		if (status & ATMEL_SPI_SR_OVRES)
+			return -1;
+
+		if ((len_tx < len) && (status & ATMEL_SPI_SR_TDRE)) {
+			if (txp)
+				value = *txp++;
+			else
+				value = 0;
+			writel(value, &reg_base->tdr);
+			len_tx++;
+		}
+
+		if (status & ATMEL_SPI_SR_RDRF) {
+			value = readl(&reg_base->rdr);
+			if (rxp)
+				*rxp++ = value;
+			len_rx++;
+		}
+	}
+
+out:
+	if (flags & SPI_XFER_END) {
+		/*
+		 * Wait until the transfer is completely done before
+		 * we deactivate CS.
+		 */
+		wait_for_bit(__func__, &reg_base->sr,
+			     ATMEL_SPI_SR_TXEMPTY, true, 1000, false);
+
+		atmel_spi_cs_deactivate(dev);
+	}
+
+	return 0;
+}
+
+static int atmel_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+
+	priv->freq = speed;
+
+	return 0;
+}
+
+static int atmel_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+
+	priv->mode = mode;
+
+	return 0;
+}
+
+static const struct dm_spi_ops atmel_spi_ops = {
+	.claim_bus	= atmel_spi_claim_bus,
+	.release_bus	= atmel_spi_release_bus,
+	.xfer		= atmel_spi_xfer,
+	.set_speed	= atmel_spi_set_speed,
+	.set_mode	= atmel_spi_set_mode,
+	/*
+	 * cs_info is not needed, since we require all chip selects to be
+	 * in the device tree explicitly
+	 */
+};
+
+static int atmel_spi_enable_clk(struct udevice *bus)
+{
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+	struct clk clk;
+	ulong clk_rate;
+	int ret;
+
+	ret = clk_get_by_index(bus, 0, &clk);
+	if (ret)
+		return -EINVAL;
+
+	ret = clk_enable(&clk);
+	if (ret)
+		return ret;
+
+	clk_rate = clk_get_rate(&clk);
+	if (!clk_rate)
+		return -EINVAL;
+
+	priv->bus_clk_rate = clk_rate;
+
+	clk_free(&clk);
+
+	return 0;
+}
+
+static int atmel_spi_probe(struct udevice *bus)
+{
+	struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus);
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+	int i, ret;
+
+	ret = atmel_spi_enable_clk(bus);
+	if (ret)
+		return ret;
+
+	bus_plat->regs = (struct at91_spi *)dev_get_addr(bus);
+
+	ret = gpio_request_list_by_name(bus, "cs-gpios", priv->cs_gpios,
+					ARRAY_SIZE(priv->cs_gpios), 0);
+	if (ret < 0) {
+		error("Can't get %s gpios! Error: %d", bus->name, ret);
+		return ret;
+	}
+
+	for(i = 0; i < ARRAY_SIZE(priv->cs_gpios); i++) {
+		dm_gpio_set_dir_flags(&priv->cs_gpios[i],
+				      GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+	}
+
+	writel(ATMEL_SPI_CR_SWRST, &bus_plat->regs->cr);
+
+	return 0;
+}
+
+static const struct udevice_id atmel_spi_ids[] = {
+	{ .compatible = "atmel,at91rm9200-spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(atmel_spi) = {
+	.name	= "atmel_spi",
+	.id	= UCLASS_SPI,
+	.of_match = atmel_spi_ids,
+	.ops	= &atmel_spi_ops,
+	.platdata_auto_alloc_size = sizeof(struct atmel_spi_platdata),
+	.priv_auto_alloc_size = sizeof(struct atmel_spi_priv),
+	.probe	= atmel_spi_probe,
+};
+#endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [U-Boot] [U-Boot, v11] dm: at91: Add driver model support for the spi driver
  2016-10-28  6:17 [U-Boot] [PATCH v11] dm: at91: Add driver model support for the spi driver Wenyou Yang
@ 2016-10-28 16:49 ` Andreas Bießmann
  2016-10-28 18:07   ` Jagan Teki
  0 siblings, 1 reply; 4+ messages in thread
From: Andreas Bießmann @ 2016-10-28 16:49 UTC (permalink / raw)
  To: u-boot

Dear Wenyou Yang,

Wenyou Yang <wenyou.yang@atmel.com> writes:
>Add driver model support while retaining the existing legacy code.
>This allows the driver to support boards that have converted to
>driver model as well as those that have not.
>
>Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
>Reviewed-by: Simon Glass <sjg@chromium.org>
>Acked-by: Stephen Warren <swarren@nvidia.com>
>---
>
>Changes in v11:
> - Set cs_gpio direction to output and active.
> - Use wait_for_bit() to replace do {} while ().
> - Add more description for help of ATMEL_SPI.
>
>Changes in v10:
> - Add Acked-by tag.
>
>Changes in v9:
> - Due to the peripheral clock driver improvement, remove the
>   unneccessary clock calling.
>
>Changes in v8:
> - Fix compile error for AVR32.
>
>Changes in v7:
> - Move gpio_request_list_by_name() to _probe(), remove
>   *_ofdata_to_platdata().
>
>Changes in v6:
> - Remove the two flash related options.
>
>Changes in v5:
> - Change clk_client.h -> clk.h to adapt to clk API conversion.
>
>Changes in v4:
> - Collect Reviewed-by tag.
> - Update the clk API based on [PATCH] clk: convert API to match
>   reset/mailbox fstyle (http://patchwork.ozlabs.org/patch/625342/).
> - Remove check on dev_get_parent() return.
> - Fixed the return value, -ENODEV->-EINVAL.
> - Retain #include <asm/arch/clk.h> line.
>
>Changes in v3:
> - Remove redundant log print.
>
>Changes in v2:
> - Add clock support.
>
> drivers/spi/Kconfig     |   8 ++
> drivers/spi/atmel_spi.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 296 insertions(+)

applied to u-boot-atmel/master, thanks!

Best regards,
Andreas Bie?mann

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] [U-Boot, v11] dm: at91: Add driver model support for the spi driver
  2016-10-28 16:49 ` [U-Boot] [U-Boot, " Andreas Bießmann
@ 2016-10-28 18:07   ` Jagan Teki
  2016-10-28 21:19     ` Andreas Bießmann
  0 siblings, 1 reply; 4+ messages in thread
From: Jagan Teki @ 2016-10-28 18:07 UTC (permalink / raw)
  To: u-boot

On Fri, Oct 28, 2016 at 10:19 PM, Andreas Bie?mann
<andreas@biessmann.org> wrote:
> Dear Wenyou Yang,
>
> Wenyou Yang <wenyou.yang@atmel.com> writes:
>>Add driver model support while retaining the existing legacy code.
>>This allows the driver to support boards that have converted to
>>driver model as well as those that have not.
>>
>>Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
>>Reviewed-by: Simon Glass <sjg@chromium.org>
>>Acked-by: Stephen Warren <swarren@nvidia.com>
>>---
>>
>>Changes in v11:
>> - Set cs_gpio direction to output and active.
>> - Use wait_for_bit() to replace do {} while ().
>> - Add more description for help of ATMEL_SPI.
>>
>>Changes in v10:
>> - Add Acked-by tag.
>>
>>Changes in v9:
>> - Due to the peripheral clock driver improvement, remove the
>>   unneccessary clock calling.
>>
>>Changes in v8:
>> - Fix compile error for AVR32.
>>
>>Changes in v7:
>> - Move gpio_request_list_by_name() to _probe(), remove
>>   *_ofdata_to_platdata().
>>
>>Changes in v6:
>> - Remove the two flash related options.
>>
>>Changes in v5:
>> - Change clk_client.h -> clk.h to adapt to clk API conversion.
>>
>>Changes in v4:
>> - Collect Reviewed-by tag.
>> - Update the clk API based on [PATCH] clk: convert API to match
>>   reset/mailbox fstyle (http://patchwork.ozlabs.org/patch/625342/).
>> - Remove check on dev_get_parent() return.
>> - Fixed the return value, -ENODEV->-EINVAL.
>> - Retain #include <asm/arch/clk.h> line.
>>
>>Changes in v3:
>> - Remove redundant log print.
>>
>>Changes in v2:
>> - Add clock support.
>>
>> drivers/spi/Kconfig     |   8 ++
>> drivers/spi/atmel_spi.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 296 insertions(+)
>
> applied to u-boot-atmel/master, thanks!

Sorry, don't know how come this is applied w/o any Ack/Review tag from
the maintainer?

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] [U-Boot, v11] dm: at91: Add driver model support for the spi driver
  2016-10-28 18:07   ` Jagan Teki
@ 2016-10-28 21:19     ` Andreas Bießmann
  0 siblings, 0 replies; 4+ messages in thread
From: Andreas Bießmann @ 2016-10-28 21:19 UTC (permalink / raw)
  To: u-boot

Hi Jagan,

On 28.10.16 20:07, Jagan Teki wrote:
> On Fri, Oct 28, 2016 at 10:19 PM, Andreas Bie?mann
> <andreas@biessmann.org> wrote:
>> Dear Wenyou Yang,
>>
>> Wenyou Yang <wenyou.yang@atmel.com> writes:
>>> Add driver model support while retaining the existing legacy code.
>>> This allows the driver to support boards that have converted to
>>> driver model as well as those that have not.
>>>
>>> Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
>>> Reviewed-by: Simon Glass <sjg@chromium.org>
>>> Acked-by: Stephen Warren <swarren@nvidia.com>
>>> ---
>>>
>>> Changes in v11:
>>> - Set cs_gpio direction to output and active.
>>> - Use wait_for_bit() to replace do {} while ().
>>> - Add more description for help of ATMEL_SPI.
>>>
>>> Changes in v10:
>>> - Add Acked-by tag.
>>>
>>> Changes in v9:
>>> - Due to the peripheral clock driver improvement, remove the
>>>   unneccessary clock calling.
>>>
>>> Changes in v8:
>>> - Fix compile error for AVR32.
>>>
>>> Changes in v7:
>>> - Move gpio_request_list_by_name() to _probe(), remove
>>>   *_ofdata_to_platdata().
>>>
>>> Changes in v6:
>>> - Remove the two flash related options.
>>>
>>> Changes in v5:
>>> - Change clk_client.h -> clk.h to adapt to clk API conversion.
>>>
>>> Changes in v4:
>>> - Collect Reviewed-by tag.
>>> - Update the clk API based on [PATCH] clk: convert API to match
>>>   reset/mailbox fstyle (http://patchwork.ozlabs.org/patch/625342/).
>>> - Remove check on dev_get_parent() return.
>>> - Fixed the return value, -ENODEV->-EINVAL.
>>> - Retain #include <asm/arch/clk.h> line.
>>>
>>> Changes in v3:
>>> - Remove redundant log print.
>>>
>>> Changes in v2:
>>> - Add clock support.
>>>
>>> drivers/spi/Kconfig     |   8 ++
>>> drivers/spi/atmel_spi.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++++
>>> 2 files changed, 296 insertions(+)
>>
>> applied to u-boot-atmel/master, thanks!
> 
> Sorry, don't know how come this is applied w/o any Ack/Review tag from
> the maintainer?
> 

This patch is now in v11 and posted first in April this year, it was
most times delegated to me [1]. Sorry, when adding it today I did not
think of asking for your reviewed/acked-by. I try to respect this in future.

With your comment here I started a retrospective on this patch and
figured out it was once delegated to you (v7) and got a reviewed-by from
you which did not make it into the patch.
Do you have any objections? Should I remove this patch from the pull
request?

Andreas

[1]
http://patchwork.ozlabs.org/project/uboot/list/?submitter=&state=*&q=dm%3A+at91%3A+Add+driver+model+support+for+the+spi+driver&archive=&delegate=

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-10-28 21:19 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-28  6:17 [U-Boot] [PATCH v11] dm: at91: Add driver model support for the spi driver Wenyou Yang
2016-10-28 16:49 ` [U-Boot] [U-Boot, " Andreas Bießmann
2016-10-28 18:07   ` Jagan Teki
2016-10-28 21:19     ` Andreas Bießmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.