All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v4 5/8] mips: ath79: add spi driver
Date: Sat, 26 Dec 2015 14:23:39 +0100	[thread overview]
Message-ID: <567E94DB.7040704@gmail.com> (raw)
In-Reply-To: <BLU436-SMTP1055E7F428BFBC6156AB133FFF80@phx.gbl>



Am 25.12.2015 um 19:56 schrieb Wills Wang:
> Signed-off-by: Wills Wang <wills.wang@live.com>
> ---
> 
> Changes in v4: None
> Changes in v3: None
> Changes in v2: None
> 
>  drivers/spi/Kconfig     |   8 ++
>  drivers/spi/Makefile    |   1 +
>  drivers/spi/ath79_spi.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 220 insertions(+)
>  create mode 100644 drivers/spi/ath79_spi.c
> 
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 2cdb110..a9e1d31 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -23,6 +23,14 @@ config ALTERA_SPI
>  	  IP core. Please find details on the "Embedded Peripherals IP
>  	  User Guide" of Altera.
>  
> +config ATH79_SPI
> +	bool "Atheros SPI driver"
> +	help
> +	  Enable the Atheros ar7xxx/ar9xxx SoC SPI driver, it was used
> +	  to access SPI NOR flash and other SPI peripherals. This driver
> +	  uses driver model and requires a device tree binding to
> +	  operate.
> +
>  config CADENCE_QSPI
>  	bool "Cadence QSPI driver"
>  	help
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index 3eca745..7fb2926 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -17,6 +17,7 @@ endif
>  
>  obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>  obj-$(CONFIG_ARMADA100_SPI) += armada100_spi.o
> +obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>  obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>  obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
>  obj-$(CONFIG_BFIN_SPI) += bfin_spi.o
> diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c
> new file mode 100644
> index 0000000..dcce584
> --- /dev/null
> +++ b/drivers/spi/ath79_spi.c
> @@ -0,0 +1,211 @@
> +/*
> + * (C) Copyright 2015
> + * Wills Wang, <wills.wang@live.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <spi.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <asm/io.h>
> +#include <asm/addrspace.h>
> +#include <asm/types.h>
> +#include <asm/arch/ar71xx_regs.h>

#include <mach/ar71xx_regs.h>

> +
> +/* CLOCK_DIVIDER = 3 (SPI clock = 200 / 8 ~ 25 MHz) */
> +#define SPI_CLK_DIV(x)     (((x) >> 1) - 1)
> +
> +struct ath79_spi_platdata {
> +	void __iomem *regs;
> +};

again, platdata is not needed

> +
> +struct ath79_spi_priv {
> +	void __iomem *regs;
> +};
> +
> +static inline u32 ath79_spi_read(struct udevice *bus, u32 offset)
> +{
> +	struct ath79_spi_priv *priv = dev_get_priv(bus);
> +	return readl(priv->regs + offset);
> +}
> +
> +static inline void ath79_spi_write(struct udevice *bus,
> +					u32 val, u32 offset)
> +{
> +	struct ath79_spi_priv *priv = dev_get_priv(bus);
> +	writel(val, priv->regs + offset);
> +}
> +
> +static int ath79_spi_claim_bus(struct udevice *dev)
> +{
> +	return 0;
> +}
> +
> +static int ath79_spi_release_bus(struct udevice *dev)
> +{
> +	return 0;
> +}
> +
> +static int ath79_spi_xfer(struct udevice *dev, unsigned int bitlen,
> +		const void *dout, void *din, unsigned long flags)
> +{
> +	struct udevice *bus = dev->parent;
> +	struct dm_spi_slave_platdata *slave = dev_get_parent_platdata(dev);
> +	uint8_t *rx = din;
> +	const uint8_t *tx = dout;
> +	uint8_t curbyte, curbitlen, restbits;
> +	uint32_t bytes = bitlen / 8;
> +	uint32_t out;
> +	uint32_t in;
> +
> +	if (flags & SPI_XFER_BEGIN) {
> +		ath79_spi_write(bus, AR71XX_SPI_FS_GPIO, AR71XX_SPI_REG_FS);
> +		ath79_spi_write(bus, AR71XX_SPI_IOC_CS_ALL, AR71XX_SPI_REG_IOC);
> +	}
> +
> +	restbits = (bitlen % 8);
> +	if (restbits)
> +		bytes++;
> +
> +	/* enable chip select */
> +	out = AR71XX_SPI_IOC_CS_ALL & ~(AR71XX_SPI_IOC_CS(slave->cs));
> +	while (bytes--) {
> +		curbyte = 0;
> +		if (tx)
> +			curbyte = *tx++;
> +
> +		if (restbits) {
> +			curbitlen = restbits;
> +			curbyte <<= 8 - restbits;
> +		} else {
> +			curbitlen = 8;
> +		}
> +
> +		/* clock starts at inactive polarity */
> +		for (curbyte <<= (8 - curbitlen); curbitlen; curbitlen--) {
> +			if (curbyte & 0x80)
> +				out |= AR71XX_SPI_IOC_DO;
> +			else
> +				out &= ~(AR71XX_SPI_IOC_DO);
> +
> +			/* setup MSB (to slave) on trailing edge */
> +			ath79_spi_write(bus, out, AR71XX_SPI_REG_IOC);
> +			ath79_spi_write(bus, out | AR71XX_SPI_IOC_CLK,
> +					AR71XX_SPI_REG_IOC);
> +			curbyte <<= 1;
> +		}
> +
> +		in = ath79_spi_read(bus, AR71XX_SPI_REG_RDS);
> +		if (rx) {
> +			if (restbits)
> +				*rx++ = (in << (8 - restbits));
> +			else
> +				*rx++ = in;
> +		}
> +	}
> +
> +	if (flags & SPI_XFER_END) {
> +		ath79_spi_write(bus, AR71XX_SPI_IOC_CS(slave->cs),
> +				AR71XX_SPI_REG_IOC);
> +		ath79_spi_write(bus, AR71XX_SPI_IOC_CS_ALL, AR71XX_SPI_REG_IOC);
> +		ath79_spi_write(bus, 0, AR71XX_SPI_REG_FS);
> +	}
> +
> +	return 0;
> +}
> +
> +
> +static int ath79_spi_set_speed(struct udevice *bus, uint speed)
> +{
> +	u32 val, div = 0;
> +
> +	if (speed)
> +		div = get_bus_freq(0) / speed;
> +
> +	if (div > 63)
> +		div = 63;
> +
> +	if (div < 5)
> +		div = 5;
> +
> +	ath79_spi_write(bus, AR71XX_SPI_FS_GPIO, AR71XX_SPI_REG_FS);
> +	val = ath79_spi_read(bus, AR71XX_SPI_REG_CTRL);
> +	val &= ~AR71XX_SPI_CTRL_DIV_MASK;
> +	val |= SPI_CLK_DIV(div);
> +	ath79_spi_write(bus, val, AR71XX_SPI_REG_CTRL);
> +	ath79_spi_write(bus, 0, AR71XX_SPI_REG_FS);
> +	return 0;
> +}
> +
> +static int ath79_spi_set_mode(struct udevice *bus, uint mode)
> +{
> +	return 0;
> +}
> +
> +static int ath79_spi_probe(struct udevice *bus)
> +{
> +	struct ath79_spi_priv *priv = dev_get_priv(bus);
> +	struct ath79_spi_platdata *plat = dev_get_platdata(bus);
> +
> +	priv->regs = plat->regs;
> +
> +	/* Init SPI Hardware, disable remap, set clock */
> +	ath79_spi_write(bus, AR71XX_SPI_FS_GPIO, AR71XX_SPI_REG_FS);
> +	ath79_spi_write(bus, AR71XX_SPI_CTRL_RD | SPI_CLK_DIV(8),
> +			AR71XX_SPI_REG_CTRL);
> +	ath79_spi_write(bus, 0, AR71XX_SPI_REG_FS);
> +
> +	return 0;
> +}
> +
> +static int ath79_cs_info(struct udevice *bus, uint cs,
> +			   struct spi_cs_info *info)
> +{
> +	/* Always allow activity on CS 0/1/2 */
> +	if (cs >= 3)
> +		return -ENODEV;
> +
> +	return 0;
> +}
> +
> +static int ath79_spi_ofdata_to_platdata(struct udevice *bus)
> +{
> +	struct ath79_spi_platdata *plat = dev_get_platdata(bus);
> +	fdt_addr_t addr;
> +
> +	addr = dev_get_addr(bus);
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	plat->regs = map_physmem(addr,
> +				 AR71XX_SPI_SIZE,
> +				 MAP_NOCACHE);

move this code to function ath79_spi_probe and drop this function

> +	return 0;
> +}
> +
> +static const struct dm_spi_ops ath79_spi_ops = {
> +	.claim_bus  = ath79_spi_claim_bus,
> +	.release_bus    = ath79_spi_release_bus,
> +	.xfer       = ath79_spi_xfer,
> +	.set_speed  = ath79_spi_set_speed,
> +	.set_mode   = ath79_spi_set_mode,
> +	.cs_info    = ath79_cs_info,
> +};
> +
> +static const struct udevice_id ath79_spi_ids[] = {
> +	{ .compatible = "ath79,ath79-spi" },
> +	{}
> +};
> +
> +U_BOOT_DRIVER(ath79_spi) = {
> +	.name   = "ath79_spi",
> +	.id = UCLASS_SPI,
> +	.of_match = ath79_spi_ids,
> +	.ops    = &ath79_spi_ops,
> +	.ofdata_to_platdata = ath79_spi_ofdata_to_platdata,
> +	.platdata_auto_alloc_size = sizeof(struct ath79_spi_platdata),

again, no platdata needed

> +	.priv_auto_alloc_size = sizeof(struct ath79_spi_priv),
> +	.probe  = ath79_spi_probe,
> +};
> 

-- 
- Daniel

  reply	other threads:[~2015-12-26 13:23 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1451069788-6786-1-git-send-email-wills.wang@live.com>
2015-12-25 18:56 ` [U-Boot] [PATCH v4 1/8] include: Add support for "do_div" macro Wills Wang
2015-12-26  7:24   ` Marek Vasut
2015-12-26 15:48     ` Wills Wang
2015-12-26 13:09   ` Daniel Schwierzeck
2015-12-26 16:54     ` Wills Wang
2015-12-25 18:56 ` [U-Boot] [PATCH v4 2/8] mips: implement to access the KSEG0/1 memory range in map_physmem Wills Wang
2015-12-26  7:25   ` Marek Vasut
2015-12-25 18:56 ` [U-Boot] [PATCH v4 3/8] mips: add base support for atheros ath79 based SOCs Wills Wang
2015-12-26  7:28   ` Marek Vasut
2015-12-26 16:17     ` Wills Wang
2015-12-26 17:01       ` Daniel Schwierzeck
2015-12-26 17:06         ` Marek Vasut
2015-12-27  9:37         ` Wills Wang
2015-12-25 18:56 ` [U-Boot] [PATCH v4 4/8] mips: ath79: add serial driver for ar933x SOC Wills Wang
2015-12-26 13:20   ` Daniel Schwierzeck
2015-12-26 16:54     ` Wills Wang
2015-12-26 17:19       ` Daniel Schwierzeck
2015-12-27  6:28     ` Wills Wang
2015-12-27  8:21       ` Thomas Chou
2015-12-27 13:07         ` Thomas Chou
2015-12-27  8:31     ` Thomas Chou
2015-12-25 18:56 ` [U-Boot] [PATCH v4 5/8] mips: ath79: add spi driver Wills Wang
2015-12-26 13:23   ` Daniel Schwierzeck [this message]
2015-12-26 16:56     ` Wills Wang
2015-12-25 18:56 ` [U-Boot] [PATCH v4 6/8] mips: ath79: add AP121 reference board Wills Wang
2015-12-26 13:52   ` Daniel Schwierzeck
2015-12-26 16:59     ` Wills Wang
2015-12-26 17:07       ` Daniel Schwierzeck
2015-12-27  6:36     ` Wills Wang
2015-12-27  6:41       ` Marek Vasut
2015-12-27  7:03         ` Wills Wang
2015-12-27  7:10           ` Marek Vasut
2015-12-25 18:56 ` [U-Boot] [PATCH v4 7/8] mips: support optimize tuning for same common processor cores Wills Wang
2015-12-26  7:30   ` Marek Vasut
2015-12-26 18:58   ` Daniel Schwierzeck
2015-12-27  3:03     ` Wills Wang
2015-12-25 18:56 ` [U-Boot] [PATCH v4 8/8] mips: move optimize tuning option from deprecated config.mk to Kconfig Wills Wang
2015-12-26  7:30   ` Marek Vasut
2015-12-26 17:33     ` Wills Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=567E94DB.7040704@gmail.com \
    --to=daniel.schwierzeck@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.