From patchwork Thu Sep 14 01:25:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andes X-Patchwork-Id: 813679 X-Patchwork-Delegate: uboot@andestech.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xt1gb54kqz9t2l for ; Thu, 14 Sep 2017 11:50:03 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 5D2A9C21DB8; Thu, 14 Sep 2017 01:50:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id A2FDDC21C3F; Thu, 14 Sep 2017 01:49:58 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id B9007C21C3C; Thu, 14 Sep 2017 01:49:56 +0000 (UTC) Received: from ATCSQR.andestech.com (exmail.andestech.com [59.124.169.137]) by lists.denx.de (Postfix) with ESMTPS id A1239C21C3F for ; Thu, 14 Sep 2017 01:49:55 +0000 (UTC) Received: from mail.andestech.com (atcpcs16.andestech.com [10.0.1.222]) by ATCSQR.andestech.com with ESMTP id v8E1hiPG063277; Thu, 14 Sep 2017 09:43:44 +0800 (GMT-8) (envelope-from uboot@andestech.com) Received: from app09.andestech.com (10.0.4.97) by ATCPCS16.andestech.com (10.0.1.222) with Microsoft SMTP Server id 14.3.123.3; Thu, 14 Sep 2017 09:49:22 +0800 From: Andes To: , , Date: Thu, 14 Sep 2017 09:25:51 +0800 Message-ID: <1505352351-12161-1-git-send-email-uboot@andestech.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-Originating-IP: [10.0.4.97] X-DNSRBL: X-MAIL: ATCSQR.andestech.com v8E1hiPG063277 Subject: [U-Boot] [PATCH 1/3] nds32: mtd: add spi flash id MX25U16335E. X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: rick To support MACRONIX MX25U1635E 16M-BIT flash. Signed-off-by: rick --- drivers/mtd/spi/spi_flash_ids.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/spi/spi_flash_ids.c b/drivers/mtd/spi/spi_flash_ids.c index c4ccf48..b2ab439 100644 --- a/drivers/mtd/spi/spi_flash_ids.c +++ b/drivers/mtd/spi/spi_flash_ids.c @@ -83,6 +83,7 @@ const struct spi_flash_info spi_flash_ids[] = { {"mx25l51235f", INFO(0xc2201a, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP) }, {"mx25u6435f", INFO(0xc22537, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP) }, {"mx25l12855e", INFO(0xc22618, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, + {"mx25u1635e", INFO(0xc22535, 0x0, 64 * 1024, 32, SECT_4K) }, {"mx66u51235f", INFO(0xc2253a, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP) }, {"mx66l1g45g", INFO(0xc2201b, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP) }, #endif From patchwork Thu Sep 14 01:26:26 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andes X-Patchwork-Id: 813680 X-Patchwork-Delegate: uboot@andestech.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xt1hD6lmyz9t2l for ; Thu, 14 Sep 2017 11:50:36 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 9052EC21E4A; Thu, 14 Sep 2017 01:50:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 9E2DEC21DF4; Thu, 14 Sep 2017 01:50:29 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 11200C21C4F; Thu, 14 Sep 2017 01:50:19 +0000 (UTC) Received: from ATCSQR.andestech.com (exmail.andestech.com [59.124.169.137]) by lists.denx.de (Postfix) with ESMTPS id C696CC21E4B for ; Thu, 14 Sep 2017 01:50:18 +0000 (UTC) Received: from mail.andestech.com (atcpcs16.andestech.com [10.0.1.222]) by ATCSQR.andestech.com with ESMTP id v8E1iENu063332; Thu, 14 Sep 2017 09:44:15 +0800 (GMT-8) (envelope-from uboot@andestech.com) Received: from app09.andestech.com (10.0.4.97) by ATCPCS16.andestech.com (10.0.1.222) with Microsoft SMTP Server id 14.3.123.3; Thu, 14 Sep 2017 09:49:56 +0800 From: Andes To: , , Date: Thu, 14 Sep 2017 09:26:26 +0800 Message-ID: <1505352386-12196-1-git-send-email-uboot@andestech.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-Originating-IP: [10.0.4.97] X-DNSRBL: X-MAIL: ATCSQR.andestech.com v8E1iENu063332 Subject: [U-Boot] [PATCH 2/3] nds32: board: Support SPI driver. X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: rick Add spi dts node and enable spi dm flash config. Signed-off-by: rick --- arch/nds32/dts/ae3xx.dts | 23 +++++++++++++++++++++++ configs/adp-ae3xx_defconfig | 10 +++++++++- include/configs/adp-ae3xx.h | 15 +++++++++++++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/arch/nds32/dts/ae3xx.dts b/arch/nds32/dts/ae3xx.dts index 4221e4b..fbe6d74 100644 --- a/arch/nds32/dts/ae3xx.dts +++ b/arch/nds32/dts/ae3xx.dts @@ -8,6 +8,7 @@ aliases { uart0 = &serial0; ethernet0 = &mac0; + spi0 = &spi; } ; chosen { @@ -22,6 +23,12 @@ reg = <0x00000000 0x40000000>; }; + spiclk: virt_100mhz { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <100000000>; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -69,4 +76,20 @@ device-width = <1>; }; + spi: spi@f0b00000 { + compatible = "andestech,atcspi200"; + reg = <0xf0b00000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + num-cs = <1>; + clocks = <&spiclk>; + interrupts = <3 4>; + flash@0 { + compatible = "spi-flash"; + spi-max-frequency = <50000000>; + reg = <0>; + spi-cpol; + spi-cpha; + }; + }; }; diff --git a/configs/adp-ae3xx_defconfig b/configs/adp-ae3xx_defconfig index 9e1e5ec..c105395 100644 --- a/configs/adp-ae3xx_defconfig +++ b/configs/adp-ae3xx_defconfig @@ -5,6 +5,8 @@ CONFIG_FIT=y CONFIG_BOOTDELAY=3 CONFIG_SYS_PROMPT="NDS32 # " CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SF_TEST=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_CMD_PING=y @@ -13,17 +15,23 @@ CONFIG_CMD_DATE=y CONFIG_CMD_EXT2=y CONFIG_CMD_FAT=y CONFIG_OF_CONTROL=y -CONFIG_ENV_IS_IN_FLASH=y +CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y +CONFIG_CLK=y CONFIG_MMC=y CONFIG_MTD=y CONFIG_MTD_NOR_FLASH=y CONFIG_CFI_FLASH=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_MACRONIX=y CONFIG_DM_ETH=y CONFIG_FTMAC100=y CONFIG_BAUDRATE=38400 CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y +CONFIG_DM_SPI=y +CONFIG_NDS_AE3XX_SPI=y CONFIG_TIMER=y CONFIG_AE3XX_TIMER=y diff --git a/include/configs/adp-ae3xx.h b/include/configs/adp-ae3xx.h index fc04934..977a755 100644 --- a/include/configs/adp-ae3xx.h +++ b/include/configs/adp-ae3xx.h @@ -231,14 +231,25 @@ /* max number of sectors on one chip */ #define CONFIG_FLASH_SECTOR_SIZE (0x10000*2) -#define CONFIG_ENV_SECT_SIZE CONFIG_FLASH_SECTOR_SIZE #define CONFIG_SYS_MAX_FLASH_SECT 512 /* environments */ -#define CONFIG_ENV_ADDR (CONFIG_SYS_MONITOR_BASE + 0x140000) +#define CONFIG_ENV_SPI_BUS 0 +#define CONFIG_ENV_SPI_CS 0 +#define CONFIG_ENV_SPI_MAX_HZ 50000000 +#define CONFIG_ENV_SPI_MODE 0 +#define CONFIG_ENV_SECT_SIZE 0x1000 +#define CONFIG_ENV_OFFSET 0x140000 #define CONFIG_ENV_SIZE 8192 #define CONFIG_ENV_OVERWRITE + +/* SPI FLASH */ +#define CONFIG_SF_DEFAULT_BUS 0 +#define CONFIG_SF_DEFAULT_CS 0 +#define CONFIG_SF_DEFAULT_SPEED 1000000 +#define CONFIG_SF_DEFAULT_MODE 0 + /* * For booting Linux, the board info and command line data * have to be in the first 16 MB of memory, since this is From patchwork Thu Sep 14 01:26:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andes X-Patchwork-Id: 813681 X-Patchwork-Delegate: uboot@andestech.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xt1jH3bClz9t3V for ; Thu, 14 Sep 2017 11:51:31 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 34BBFC21C72; Thu, 14 Sep 2017 01:51:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 955FBC21D55; Thu, 14 Sep 2017 01:51:24 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id DFFB1C21E05; Thu, 14 Sep 2017 01:50:52 +0000 (UTC) Received: from ATCSQR.andestech.com (exmail.andestech.com [59.124.169.137]) by lists.denx.de (Postfix) with ESMTPS id 5C17CC21E1E for ; Thu, 14 Sep 2017 01:50:50 +0000 (UTC) Received: from mail.andestech.com (atcpcs16.andestech.com [10.0.1.222]) by ATCSQR.andestech.com with ESMTP id v8E1ij4b063368; Thu, 14 Sep 2017 09:44:45 +0800 (GMT-8) (envelope-from uboot@andestech.com) Received: from app09.andestech.com (10.0.4.97) by ATCPCS16.andestech.com (10.0.1.222) with Microsoft SMTP Server id 14.3.123.3; Thu, 14 Sep 2017 09:50:26 +0800 From: Andes To: , , Date: Thu, 14 Sep 2017 09:26:55 +0800 Message-ID: <1505352415-12231-1-git-send-email-uboot@andestech.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-Originating-IP: [10.0.4.97] X-DNSRBL: X-MAIL: ATCSQR.andestech.com v8E1ij4b063368 Subject: [U-Boot] [PATCH 3/3] nds32: spi: Support spi dm driver. X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: rick Support spi driver and can detect MX25U1635E flash on AE3XX board. Verification: sf probe 0:0 50000000 0 spi_flash_std_probe(sf_Probr.c) spi_flash_probe_slave(sf_Probr.c) SF: Detected mx25u1635e with page size 256 Bytes, erase size 4 KiB, total 2 MiB NDS32 # sf test 0x100000 0x1000 SPI flash test: 0 erase: 34 ticks, 117 KiB/s 0.936 Mbps 1 check: 15 ticks, 266 KiB/s 2.128 Mbps 2 write: 21 ticks, 190 KiB/s 1.520 Mbps 3 read: 11 ticks, 363 KiB/s 2.904 Mbps Test passed 0 erase: 34 ticks, 117 KiB/s 0.936 Mbps 1 check: 15 ticks, 266 KiB/s 2.128 Mbps 2 write: 21 ticks, 190 KiB/s 1.520 Mbps 3 read: 11 ticks, 363 KiB/s 2.904 Mbps Signed-off-by: rick --- drivers/spi/Kconfig | 7 + drivers/spi/Makefile | 1 + drivers/spi/nds_ae3xx_spi.c | 499 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 507 insertions(+) create mode 100644 drivers/spi/nds_ae3xx_spi.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3c5582a..88da9a4 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -210,6 +210,13 @@ config FSL_QSPI used to access the SPI NOR flash on platforms embedding this Freescale IP core. +config NDS_AE3XX_SPI + bool "Andestech AE3XX SPI driver" + help + Enable the Andestech AE3XX SPI driver. This driver can be + used to access the SPI flash on platforms embedding this + Andestech IP core. + config TI_QSPI bool "TI QSPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 9f8b86d..cd7c755 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o obj-$(CONFIG_MXC_SPI) += mxc_spi.o obj-$(CONFIG_MXS_SPI) += mxs_spi.o +obj-$(CONFIG_NDS_AE3XX_SPI) += nds_ae3xx_spi.o obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o obj-$(CONFIG_PIC32_SPI) += pic32_spi.o obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o diff --git a/drivers/spi/nds_ae3xx_spi.c b/drivers/spi/nds_ae3xx_spi.c new file mode 100644 index 0000000..f5bd99a --- /dev/null +++ b/drivers/spi/nds_ae3xx_spi.c @@ -0,0 +1,499 @@ +/* + * NDS SPI controller driver. + * + * Copyright 2017 Andes Technology, Inc. + * Author: Rick Chen (rick@andestech.com) + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define MAX_TRANSFER_LEN 512 +#define CHUNK_SIZE 1 +#define SPI_TIMEOUT 0x100000 +#define SPI0_BUS 0 +#define SPI1_BUS 1 +#define SPI0_BASE 0xf0b00000 +#define SPI1_BASE 0xf0f00000 +#define NSPI_MAX_CS_NUM 1 + +struct ae3xx_spi_regs { + u32 rev; + u32 reserve1[3]; + u32 format; /* 0x10 */ +#define DATA_LENGTH(x) ((x-1)<<8) + u32 pio; + u32 reserve2[2]; + u32 tctrl; /* 0x20 */ +#define TRAMODE_OFFSET 24 +#define TRAMODE_MASK (0x0F<regs->timing; + tm &= ~SCLK_DIV_MASK; + + if(ns->freq >= ns->clock) + div =0xff; + else{ + for (div = 0; div < 0xff; div++) { + if (ns->freq >= ns->clock / (2 * (div + 1))) + break; + } + } + + tm |= div; + ns->regs->timing = tm; + + return 0; + +} + +static int __ae3xx_spi_claim_bus(struct nds_spi_slave *ns) +{ + unsigned int format=0; + ns->regs->ctrl |= (TXFRST|RXFRST|SPIRST); + while((ns->regs->ctrl &(TXFRST|RXFRST|SPIRST))&&(ns->to--)) + if(!ns->to) + return -EINVAL; + + ns->cmd_len = 0; + format = ns->mode|DATA_LENGTH(8); + ns->regs->format = format; + __ae3xx_spi_set_speed(ns); + + return 0; +} + +static int __ae3xx_spi_release_bus(struct nds_spi_slave *ns) +{ + /* do nothing */ + return 0; +} + +static int __ae3xx_spi_start(struct nds_spi_slave *ns) +{ + int i,olen=0; + int tc = ns->regs->tctrl; + + tc &= ~(WCNT_MASK|RCNT_MASK|TRAMODE_MASK); + if ((ns->din)&&(ns->cmd_len)) + tc |= TRAMODE_WR; + else if (ns->din) + tc |= TRAMODE_RO; + else + tc |= TRAMODE_WO; + + if(ns->dout) + olen = ns->tran_len; + tc |= (ns->cmd_len+olen-1) << WCNT_OFFSET; + + if(ns->din) + tc |= (ns->tran_len-1) << RCNT_OFFSET; + + ns->regs->tctrl = tc; + ns->regs->cmd = 1; + + for (i=0;icmd_len;i++) + ns->regs->data = ns->cmd_buf[i]; + + return 0; +} + +static int __ae3xx_spi_stop(struct nds_spi_slave *ns) +{ + ns->regs->timing = ns->mtiming; + while ((ns->regs->status & SPIBSY)&&(ns->to--)) + if (!ns->to) + return -EINVAL; + + return 0; +} + +static void __nspi_espi_tx(struct nds_spi_slave *ns, const void *dout) +{ + ns->regs->data = *(u8 *)dout; +} + +static int __nspi_espi_rx(struct nds_spi_slave *ns, void *din, unsigned int bytes) +{ + *(u8 *)din = ns->regs->data; + return bytes; +} + + +static int __ae3xx_spi_xfer(struct nds_spi_slave *ns, + unsigned int bitlen, const void *data_out, void *data_in, + unsigned long flags) +{ + unsigned int event, rx_bytes; + const void *dout = NULL; + void *din = NULL; + int num_blks, num_chunks, max_tran_len, tran_len; + int num_bytes; + u8 *cmd_buf = ns->cmd_buf; + size_t cmd_len = ns->cmd_len; + size_t data_len = bitlen / 8; + int rf_cnt; + int ret = 0; + + max_tran_len = ns->max_transfer_length; + switch (flags) { + case SPI_XFER_BEGIN: + cmd_len = ns->cmd_len = data_len; + memcpy(cmd_buf, data_out, cmd_len); + return 0; + + case 0: + case SPI_XFER_END: + if (bitlen == 0) { + return 0; + } + ns->data_len = data_len; + ns->din = (u8 *)data_in; + ns->dout = (u8 *)data_out; + break; + + case SPI_XFER_BEGIN | SPI_XFER_END: + ns->data_len = 0; + ns->din = 0; + ns->dout = 0; + cmd_len = ns->cmd_len = data_len; + memcpy(cmd_buf, data_out, cmd_len); + data_out = 0; + data_len = 0; + __ae3xx_spi_start(ns); + break; + } + debug("spi_xfer: data_out %08X(%p) data_in %08X(%p) data_len %u\n", + *(uint *)data_out, data_out, *(uint *)data_in, data_in, data_len); + num_chunks = DIV_ROUND_UP(data_len, max_tran_len); + din = data_in; + dout = data_out; + while (num_chunks--) { + tran_len = min(data_len, (size_t)max_tran_len); + ns->tran_len = tran_len; + num_blks = DIV_ROUND_UP(tran_len , CHUNK_SIZE); + num_bytes = (tran_len) % CHUNK_SIZE; + if(num_bytes == 0) + num_bytes = CHUNK_SIZE; + __ae3xx_spi_start(ns); + + while (num_blks) { + event = in_le32(&ns->regs->status); + if ((event & TXEPTY) && (data_out)) { + __nspi_espi_tx(ns, dout); + num_blks -= CHUNK_SIZE; + dout += CHUNK_SIZE; + } + + if ((event & RXFVE_MASK) && (data_in)) { + rf_cnt = ((event & RXFVE_MASK)>> RXFVE_OFFSET); + if (rf_cnt >= CHUNK_SIZE) + rx_bytes = CHUNK_SIZE; + else if (num_blks == 1 && rf_cnt == num_bytes) + rx_bytes = num_bytes; + else + continue; + + if (__nspi_espi_rx(ns, din, rx_bytes) == rx_bytes) { + num_blks -= CHUNK_SIZE; + din = (unsigned char *)din + rx_bytes; + } + } + } + + data_len -= tran_len; + if(data_len) + { + ns->cmd_buf[1] += ((tran_len>>16)&0xff); + ns->cmd_buf[2] += ((tran_len>>8)&0xff); + ns->cmd_buf[3] += ((tran_len)&0xff); + ns->data_len = data_len; + } + ret = __ae3xx_spi_stop(ns); + } + ret = __ae3xx_spi_stop(ns); + + return ret; +} + +#ifndef CONFIG_DM_SPI +#define to_nds_spi_slave(s) container_of(s, struct nds_spi_slave, slave) +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + struct nds_spi_slave *ns; + + if (!spi_cs_is_valid(bus, cs)) + return NULL; + + ns = spi_alloc_slave(struct nds_spi_slave, bus, cs); + + switch (bus) { + case SPI0_BUS: + ns->regs = (struct ae3xx_spi_regs *)SPI0_BASE; + break; + + case SPI1_BUS: + ns->regs = (struct ae3xx_spi_regs *)SPI1_BASE; + break; + + default: + return NULL; + } + + ns->freq= max_hz; + ns->mode = mode; + ns->to = SPI_TIMEOUT; + ns->max_transfer_length = MAX_TRANSFER_LEN; + ns->slave.max_write_size = MAX_TRANSFER_LEN; + if (!ns) + return NULL; + + return &ns->slave; +} + +void spi_free_slave(struct spi_slave *slave) +{ + struct nds_spi_slave *ns = to_nds_spi_slave(slave); + free(ns); +} + +void spi_init(void) +{ + /* do nothing */ +} + +int spi_claim_bus(struct spi_slave *slave) +{ + struct nds_spi_slave *ns = to_nds_spi_slave(slave); + return __ae3xx_spi_claim_bus(ns); +} + +void spi_release_bus(struct spi_slave *slave) +{ + struct nds_spi_slave *ns = to_nds_spi_slave(slave); + __ae3xx_spi_release_bus(ns); +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, + void *data_in, unsigned long flags) +{ + struct nds_spi_slave *ns = to_nds_spi_slave(slave); + return __ae3xx_spi_xfer(ns, bitlen, data_out, data_in, flags); +} + +int spi_cs_is_valid(unsigned int bus, unsigned int cs) +{ + return bus == 0 && cs < NSPI_MAX_CS_NUM; +} + +void spi_cs_activate(struct spi_slave *slave) +{ + struct nds_spi_slave *ns = to_nds_spi_slave(slave); + __ae3xx_spi_start(ns); +} + +void spi_cs_deactivate(struct spi_slave *slave) +{ + struct nds_spi_slave *ns = to_nds_spi_slave(slave); + __ae3xx_spi_stop(ns); +} +#else +static int ae3xx_spi_set_speed(struct udevice *bus, uint max_hz) +{ + struct nds_spi_slave *ns = dev_get_priv(bus); + + debug("%s speed %u\n", __func__, max_hz); + + ns->freq = max_hz; + __ae3xx_spi_set_speed(ns); + + return 0; +} + +static int ae3xx_spi_set_mode(struct udevice *bus, uint mode) +{ + struct nds_spi_slave *ns = dev_get_priv(bus); + + debug("%s mode %u\n", __func__, mode); + ns->mode = mode; + + return 0; +} + +static int ae3xx_spi_claim_bus(struct udevice *dev) +{ + struct dm_spi_slave_platdata *slave_plat = + dev_get_parent_platdata(dev); + struct udevice *bus = dev->parent; + struct nds_spi_slave *ns = dev_get_priv(bus); + + if (slave_plat->cs >= ns->num_cs) { + printf("Invalid SPI chipselect\n"); + return -EINVAL; + } + + return __ae3xx_spi_claim_bus(ns); +} + +static int ae3xx_spi_release_bus(struct udevice *dev) +{ + struct nds_spi_slave *ns = dev_get_priv(dev->parent); + + return __ae3xx_spi_release_bus(ns); +} + +static int ae3xx_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, + unsigned long flags) +{ + struct udevice *bus = dev->parent; + struct nds_spi_slave *ns = dev_get_priv(bus); + + return __ae3xx_spi_xfer(ns, bitlen, dout, din, flags); +} + +static int ae3xx_spi_get_clk(struct udevice *bus) +{ + struct nds_spi_slave *ns = dev_get_priv(bus); + struct clk clk; + ulong clk_rate; + int ret; + + ret = clk_get_by_index(bus, 0, &clk); + if (ret) + return -EINVAL; + + clk_rate = clk_get_rate(&clk); + if (!clk_rate) + return -EINVAL; + + ns->clock = clk_rate; + clk_free(&clk); + + return 0; +} + +static int ae3xx_spi_probe(struct udevice *bus) +{ + struct nds_spi_slave *ns = dev_get_priv(bus); + + ns->to = SPI_TIMEOUT; + ns->max_transfer_length = MAX_TRANSFER_LEN; + ns->mtiming = ns->regs->timing; + ae3xx_spi_get_clk(bus); + + return 0; +} + +static int ae3xx_ofdata_to_platadata(struct udevice *bus) +{ + struct nds_spi_slave *ns = dev_get_priv(bus); + const void *blob = gd->fdt_blob; + int node = dev_of_offset(bus); + + ns->regs = map_physmem(devfdt_get_addr(bus), + sizeof(struct ae3xx_spi_regs), + MAP_NOCACHE); + if (!ns->regs) { + printf("%s: could not map device address\n", __func__); + return -EINVAL; + } + ns->num_cs = fdtdec_get_int(blob, node, "num-cs", 4); + + return 0; +} + +static const struct dm_spi_ops ae3xx_spi_ops = { + .claim_bus = ae3xx_spi_claim_bus, + .release_bus = ae3xx_spi_release_bus, + .xfer = ae3xx_spi_xfer, + .set_speed = ae3xx_spi_set_speed, + .set_mode = ae3xx_spi_set_mode, +}; + +static const struct udevice_id ae3xx_spi_ids[] = { + { .compatible = "andestech,atcspi200" }, + { } +}; + +U_BOOT_DRIVER(ae3xx_spi) = { + .name = "ae3xx_spi", + .id = UCLASS_SPI, + .of_match = ae3xx_spi_ids, + .ops = &ae3xx_spi_ops, + .ofdata_to_platdata = ae3xx_ofdata_to_platadata, + .priv_auto_alloc_size = sizeof(struct nds_spi_slave), + .probe = ae3xx_spi_probe, +}; +#endif