From 0e920ef052e2a5d33b1fd37b0b0ef7b74831e851 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 23 Nov 2017 11:04:34 +0800 Subject: [PATCH 01/15] ae3xx: timer: Fix ae3xx timer work abnormal in 64 bit. It will be work fine with unsigned long declaretion in timer register struct when system is 32 bit. But it will not work well when system is 64 bit. Replace it by u32 and verify both ok in 32/64 bit. Signed-off-by: Rick Chen Reviewed-by: Simon Glass --- drivers/timer/ae3xx_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/timer/ae3xx_timer.c b/drivers/timer/ae3xx_timer.c index bcc07a0c86..b710c28f6c 100644 --- a/drivers/timer/ae3xx_timer.c +++ b/drivers/timer/ae3xx_timer.c @@ -14,7 +14,7 @@ DECLARE_GLOBAL_DATA_PTR; -#define REG32_TMR(x) (*(unsigned long *) ((plat->regs) + (x>>2))) +#define REG32_TMR(x) (*(u32 *) ((plat->regs) + (x>>2))) /* * Definition of register offsets @@ -68,7 +68,7 @@ struct atctmr_timer_regs { }; struct atftmr_timer_platdata { - unsigned long *regs; + u32 *regs; }; static int atftmr_timer_get_count(struct udevice *dev, u64 *count) From fa3e354b2bcc9b07c89d0be190dd0e75cf54d6c6 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Tue, 28 Nov 2017 09:23:23 +0800 Subject: [PATCH 02/15] ae3xx: timer: Rename AE3XX to ATCPIT100 ATCPIT100 is Andestech timer IP which is embeded in AE3XX and AE250 boards. So rename AE3XX to ATCPIT100 will be more make sence. Signed-off-by: rick Signed-off-by: Rick Chen Reviewed-by: Simon Glass --- configs/adp-ae3xx_defconfig | 2 +- drivers/timer/Kconfig | 7 ++++--- drivers/timer/Makefile | 2 +- drivers/timer/{ae3xx_timer.c => atcpit100_timer.c} | 0 4 files changed, 6 insertions(+), 5 deletions(-) rename drivers/timer/{ae3xx_timer.c => atcpit100_timer.c} (100%) diff --git a/configs/adp-ae3xx_defconfig b/configs/adp-ae3xx_defconfig index a3a40bf1e9..337cee1464 100644 --- a/configs/adp-ae3xx_defconfig +++ b/configs/adp-ae3xx_defconfig @@ -35,4 +35,4 @@ CONFIG_SYS_NS16550=y CONFIG_DM_SPI=y CONFIG_NDS_AE3XX_SPI=y CONFIG_TIMER=y -CONFIG_AE3XX_TIMER=y +CONFIG_ATCPIT100_TIMER=y diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 6305bbf01c..fcfdf4e839 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -105,11 +105,12 @@ config AG101P_TIMER help Select this to enable a timer for AG01P devices. -config AE3XX_TIMER - bool "AE3XX timer support" +config ATCPIT100_TIMER + bool "ATCPIT100 timer support" depends on TIMER && NDS32 help - Select this to enable a timer for AE3XX devices. + Select this to enable a ATCPIT100 timer which will be embeded + in AE3XX, AE250 boards. config ROCKCHIP_TIMER bool "Rockchip timer support" diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index 69e8961a7b..15e515407e 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -13,6 +13,6 @@ obj-$(CONFIG_AST_TIMER) += ast_timer.o obj-$(CONFIG_STI_TIMER) += sti-timer.o obj-$(CONFIG_ARC_TIMER) += arc_timer.o obj-$(CONFIG_AG101P_TIMER) += ag101p_timer.o -obj-$(CONFIG_AE3XX_TIMER) += ae3xx_timer.o +obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o obj-$(CONFIG_ATMEL_PIT_TIMER) += atmel_pit_timer.o diff --git a/drivers/timer/ae3xx_timer.c b/drivers/timer/atcpit100_timer.c similarity index 100% rename from drivers/timer/ae3xx_timer.c rename to drivers/timer/atcpit100_timer.c From 033d408102d68950aaba0011d9e9a07d9fbcf955 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 23 Nov 2017 10:15:20 +0800 Subject: [PATCH 03/15] cosmetic: atcpit100_timer: Rename function name as atcpit100 Integrate function and struct name as atcpit100 will be more reasonable. Signed-off-by: rick Signed-off-by: Rick Chen Reviewed-by: Simon Glass --- drivers/timer/atcpit100_timer.c | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/timer/atcpit100_timer.c b/drivers/timer/atcpit100_timer.c index b710c28f6c..d5146ddfa4 100644 --- a/drivers/timer/atcpit100_timer.c +++ b/drivers/timer/atcpit100_timer.c @@ -67,51 +67,51 @@ struct atctmr_timer_regs { u32 int_mask; /* 0x38 */ }; -struct atftmr_timer_platdata { +struct atcpit_timer_platdata { u32 *regs; }; -static int atftmr_timer_get_count(struct udevice *dev, u64 *count) +static int atcpit_timer_get_count(struct udevice *dev, u64 *count) { - struct atftmr_timer_platdata *plat = dev->platdata; + struct atcpit_timer_platdata *plat = dev->platdata; u32 val; val = ~(REG32_TMR(CH_CNT(1))+0xffffffff); *count = timer_conv_64(val); return 0; } -static int atctmr_timer_probe(struct udevice *dev) +static int atcpit_timer_probe(struct udevice *dev) { - struct atftmr_timer_platdata *plat = dev->platdata; + struct atcpit_timer_platdata *plat = dev->platdata; REG32_TMR(CH_REL(1)) = 0xffffffff; REG32_TMR(CH_CTL(1)) = APB_CLK|TMR_32; REG32_TMR(CH_EN) |= CH_TMR_EN(1 , 0); return 0; } -static int atctme_timer_ofdata_to_platdata(struct udevice *dev) +static int atcpit_timer_ofdata_to_platdata(struct udevice *dev) { - struct atftmr_timer_platdata *plat = dev_get_platdata(dev); + struct atcpit_timer_platdata *plat = dev_get_platdata(dev); plat->regs = map_physmem(devfdt_get_addr(dev) , 0x100 , MAP_NOCACHE); return 0; } -static const struct timer_ops ag101p_timer_ops = { - .get_count = atftmr_timer_get_count, +static const struct timer_ops atcpit_timer_ops = { + .get_count = atcpit_timer_get_count, }; -static const struct udevice_id ag101p_timer_ids[] = { +static const struct udevice_id atcpit_timer_ids[] = { { .compatible = "andestech,atcpit100" }, {} }; -U_BOOT_DRIVER(altera_timer) = { - .name = "ae3xx_timer", +U_BOOT_DRIVER(atcpit100_timer) = { + .name = "atcpit100_timer", .id = UCLASS_TIMER, - .of_match = ag101p_timer_ids, - .ofdata_to_platdata = atctme_timer_ofdata_to_platdata, - .platdata_auto_alloc_size = sizeof(struct atftmr_timer_platdata), - .probe = atctmr_timer_probe, - .ops = &ag101p_timer_ops, + .of_match = atcpit_timer_ids, + .ofdata_to_platdata = atcpit_timer_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct atcpit_timer_platdata), + .probe = atcpit_timer_probe, + .ops = &atcpit_timer_ops, .flags = DM_FLAG_PRE_RELOC, }; From c6c85dc87d2ca044458429cb2b61c0dcaea9b7d6 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Tue, 28 Nov 2017 09:14:20 +0800 Subject: [PATCH 04/15] cosmetic: atcpit100_timer: Use device api to get platdata Use dev_get_platdata to get private platdata. Signed-off-by: rick Signed-off-by: Rick Chen Reviewed-by: Simon Glass --- drivers/timer/atcpit100_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/timer/atcpit100_timer.c b/drivers/timer/atcpit100_timer.c index d5146ddfa4..963f978d20 100644 --- a/drivers/timer/atcpit100_timer.c +++ b/drivers/timer/atcpit100_timer.c @@ -73,7 +73,7 @@ struct atcpit_timer_platdata { static int atcpit_timer_get_count(struct udevice *dev, u64 *count) { - struct atcpit_timer_platdata *plat = dev->platdata; + struct atcpit_timer_platdata *plat = dev_get_platdata(dev); u32 val; val = ~(REG32_TMR(CH_CNT(1))+0xffffffff); *count = timer_conv_64(val); @@ -82,7 +82,7 @@ static int atcpit_timer_get_count(struct udevice *dev, u64 *count) static int atcpit_timer_probe(struct udevice *dev) { - struct atcpit_timer_platdata *plat = dev->platdata; + struct atcpit_timer_platdata *plat = dev_get_platdata(dev); REG32_TMR(CH_REL(1)) = 0xffffffff; REG32_TMR(CH_CTL(1)) = APB_CLK|TMR_32; REG32_TMR(CH_EN) |= CH_TMR_EN(1 , 0); From 410d129e8c68b994dee69c89dd8e52931458ff85 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 23 Nov 2017 10:22:17 +0800 Subject: [PATCH 05/15] dt-bindings: timer: Add andestech atcpit100 timer Add a document to describe Andestech atcpit100 timer and binding information. Signed-off-by: rick Signed-off-by: Rick Chen Reviewed-by: Simon Glass --- .../timer/atcpit100_timer.txt | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 doc/device-tree-bindings/timer/atcpit100_timer.txt diff --git a/doc/device-tree-bindings/timer/atcpit100_timer.txt b/doc/device-tree-bindings/timer/atcpit100_timer.txt new file mode 100644 index 0000000000..620814e948 --- /dev/null +++ b/doc/device-tree-bindings/timer/atcpit100_timer.txt @@ -0,0 +1,31 @@ +Andestech ATCPIT100 timer +------------------------------------------------------------------ +ATCPIT100 is a generic IP block from Andes Technology, embedded in +Andestech AE3XX, AE250 platforms and other designs. + +This timer is a set of compact multi-function timers, which can be +used as pulse width modulators (PWM) as well as simple timers. + +It supports up to 4 PIT channels. Each PIT channel is a +multi-function timer and provide the following usage scenarios: +One 32-bit timer +Two 16-bit timers +Four 8-bit timers +One 16-bit PWM +One 16-bit timer and one 8-bit PWM +Two 8-bit timer and one 8-bit PWM + +Required properties: +- compatible : Should be "andestech,atcpit100" +- reg : Address and length of the register set +- interrupts : Reference to the timer interrupt +- clock-frequency : The rate in HZ in input of the Andestech ATCPIT100 timer + +Examples: + +timer0: timer@f0400000 { + compatible = "andestech,atcpit100"; + reg = <0xf0400000 0x1000>; + interrupts = <2 4>; + clock-frequency = <30000000>; +}: From 0f4a395f782a2801842492d5b365ed095a1e69ef Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 23 Nov 2017 12:48:46 +0800 Subject: [PATCH 06/15] atcpit100: timer: Remove arch dependency. ATCPIT100 is often used in AE3XX platform which is based on NDS32 architecture recently. But in the future Andestech will have AE250 platform which is embeded ATCPIT100 timer based on RISCV architecture. Signed-off-by: Rick Chen Reviewed-by: Simon Glass --- drivers/timer/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index fcfdf4e839..3a1f8311c1 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -107,7 +107,7 @@ config AG101P_TIMER config ATCPIT100_TIMER bool "ATCPIT100 timer support" - depends on TIMER && NDS32 + depends on TIMER help Select this to enable a ATCPIT100 timer which will be embeded in AE3XX, AE250 boards. From 41bbb8b333a6977cd28d31c58a5a209001ce5056 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 23 Nov 2017 14:19:36 +0800 Subject: [PATCH 07/15] spi: nds_ae3xx: Rename nds_ae3xx_spi as atcspi200_spi atcspi200 is Andestech spi ip which is embedded in AE3XX and AE250 platforms. So rename as atcspi200 will be more reasonable to be used in different platforms. Signed-off-by: Rick Chen --- configs/adp-ae3xx_defconfig | 2 +- drivers/spi/Kconfig | 10 +++++----- drivers/spi/Makefile | 2 +- drivers/spi/{nds_ae3xx_spi.c => atcspi200_spi.c} | 0 4 files changed, 7 insertions(+), 7 deletions(-) rename drivers/spi/{nds_ae3xx_spi.c => atcspi200_spi.c} (100%) diff --git a/configs/adp-ae3xx_defconfig b/configs/adp-ae3xx_defconfig index 337cee1464..38696e6f40 100644 --- a/configs/adp-ae3xx_defconfig +++ b/configs/adp-ae3xx_defconfig @@ -33,6 +33,6 @@ CONFIG_BAUDRATE=38400 CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y CONFIG_DM_SPI=y -CONFIG_NDS_AE3XX_SPI=y +CONFIG_ATCSPI200_SPI=y CONFIG_TIMER=y CONFIG_ATCPIT100_TIMER=y diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 88da9a4c8e..494639fb01 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -210,12 +210,12 @@ 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" +config ATCSPI200_SPI + bool "Andestech ATCSPI200 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. + Enable the Andestech ATCSPI200 SPI driver. This driver can be + used to access the SPI flash on AE3XX and AE250 platforms embedding + this Andestech IP core. config TI_QSPI bool "TI QSPI driver" diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index ad56203cd6..e3184db67f 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -34,7 +34,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_ATCSPI200_SPI) += atcspi200_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/atcspi200_spi.c similarity index 100% rename from drivers/spi/nds_ae3xx_spi.c rename to drivers/spi/atcspi200_spi.c From 6720e4ae7a01afa93b99a8f62b0cc98fe01abc9b Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 23 Nov 2017 14:17:35 +0800 Subject: [PATCH 08/15] cosmetic: atcspi200: Rename function name as atcspi200 Integrate function and struct name from ae3xx to atcspi200 will be more reasonable. Signed-off-by: Rick Chen --- drivers/spi/atcspi200_spi.c | 96 ++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/drivers/spi/atcspi200_spi.c b/drivers/spi/atcspi200_spi.c index f5bd99a605..3e29df03a4 100644 --- a/drivers/spi/atcspi200_spi.c +++ b/drivers/spi/atcspi200_spi.c @@ -1,5 +1,5 @@ /* - * NDS SPI controller driver. + * Andestech ATCSPI200 SPI controller driver. * * Copyright 2017 Andes Technology, Inc. * Author: Rick Chen (rick@andestech.com) @@ -25,7 +25,7 @@ DECLARE_GLOBAL_DATA_PTR; #define SPI1_BASE 0xf0f00000 #define NSPI_MAX_CS_NUM 1 -struct ae3xx_spi_regs { +struct atcspi200_spi_regs { u32 rev; u32 reserve1[3]; u32 format; /* 0x10 */ @@ -78,7 +78,7 @@ struct nds_spi_slave { #ifndef CONFIG_DM_SPI struct spi_slave slave; #endif - volatile struct ae3xx_spi_regs *regs; + volatile struct atcspi200_spi_regs *regs; int to; unsigned int freq; ulong clock; @@ -94,7 +94,7 @@ struct nds_spi_slave { unsigned int max_transfer_length; }; -static int __ae3xx_spi_set_speed(struct nds_spi_slave *ns) +static int __atcspi200_spi_set_speed(struct nds_spi_slave *ns) { u32 tm; u8 div; @@ -117,7 +117,7 @@ static int __ae3xx_spi_set_speed(struct nds_spi_slave *ns) } -static int __ae3xx_spi_claim_bus(struct nds_spi_slave *ns) +static int __atcspi200_spi_claim_bus(struct nds_spi_slave *ns) { unsigned int format=0; ns->regs->ctrl |= (TXFRST|RXFRST|SPIRST); @@ -128,18 +128,18 @@ static int __ae3xx_spi_claim_bus(struct nds_spi_slave *ns) ns->cmd_len = 0; format = ns->mode|DATA_LENGTH(8); ns->regs->format = format; - __ae3xx_spi_set_speed(ns); + __atcspi200_spi_set_speed(ns); return 0; } -static int __ae3xx_spi_release_bus(struct nds_spi_slave *ns) +static int __atcspi200_spi_release_bus(struct nds_spi_slave *ns) { /* do nothing */ return 0; } -static int __ae3xx_spi_start(struct nds_spi_slave *ns) +static int __atcspi200_spi_start(struct nds_spi_slave *ns) { int i,olen=0; int tc = ns->regs->tctrl; @@ -168,7 +168,7 @@ static int __ae3xx_spi_start(struct nds_spi_slave *ns) return 0; } -static int __ae3xx_spi_stop(struct nds_spi_slave *ns) +static int __atcspi200_spi_stop(struct nds_spi_slave *ns) { ns->regs->timing = ns->mtiming; while ((ns->regs->status & SPIBSY)&&(ns->to--)) @@ -190,7 +190,7 @@ static int __nspi_espi_rx(struct nds_spi_slave *ns, void *din, unsigned int byte } -static int __ae3xx_spi_xfer(struct nds_spi_slave *ns, +static int __atcspi200_spi_xfer(struct nds_spi_slave *ns, unsigned int bitlen, const void *data_out, void *data_in, unsigned long flags) { @@ -230,7 +230,7 @@ static int __ae3xx_spi_xfer(struct nds_spi_slave *ns, memcpy(cmd_buf, data_out, cmd_len); data_out = 0; data_len = 0; - __ae3xx_spi_start(ns); + __atcspi200_spi_start(ns); break; } debug("spi_xfer: data_out %08X(%p) data_in %08X(%p) data_len %u\n", @@ -245,7 +245,7 @@ static int __ae3xx_spi_xfer(struct nds_spi_slave *ns, num_bytes = (tran_len) % CHUNK_SIZE; if(num_bytes == 0) num_bytes = CHUNK_SIZE; - __ae3xx_spi_start(ns); + __atcspi200_spi_start(ns); while (num_blks) { event = in_le32(&ns->regs->status); @@ -279,9 +279,9 @@ static int __ae3xx_spi_xfer(struct nds_spi_slave *ns, ns->cmd_buf[3] += ((tran_len)&0xff); ns->data_len = data_len; } - ret = __ae3xx_spi_stop(ns); + ret = __atcspi200_spi_stop(ns); } - ret = __ae3xx_spi_stop(ns); + ret = __atcspi200_spi_stop(ns); return ret; } @@ -300,11 +300,11 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, switch (bus) { case SPI0_BUS: - ns->regs = (struct ae3xx_spi_regs *)SPI0_BASE; + ns->regs = (struct atcspi200_spi_regs *)SPI0_BASE; break; case SPI1_BUS: - ns->regs = (struct ae3xx_spi_regs *)SPI1_BASE; + ns->regs = (struct atcspi200_spi_regs *)SPI1_BASE; break; default: @@ -336,20 +336,20 @@ void spi_init(void) int spi_claim_bus(struct spi_slave *slave) { struct nds_spi_slave *ns = to_nds_spi_slave(slave); - return __ae3xx_spi_claim_bus(ns); + return __atcspi200_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); + __atcspi200_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); + return __atcspi200_spi_xfer(ns, bitlen, data_out, data_in, flags); } int spi_cs_is_valid(unsigned int bus, unsigned int cs) @@ -360,28 +360,28 @@ int spi_cs_is_valid(unsigned int bus, unsigned int cs) void spi_cs_activate(struct spi_slave *slave) { struct nds_spi_slave *ns = to_nds_spi_slave(slave); - __ae3xx_spi_start(ns); + __atcspi200_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); + __atcspi200_spi_stop(ns); } #else -static int ae3xx_spi_set_speed(struct udevice *bus, uint max_hz) +static int atcspi200_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); + __atcspi200_spi_set_speed(ns); return 0; } -static int ae3xx_spi_set_mode(struct udevice *bus, uint mode) +static int atcspi200_spi_set_mode(struct udevice *bus, uint mode) { struct nds_spi_slave *ns = dev_get_priv(bus); @@ -391,7 +391,7 @@ static int ae3xx_spi_set_mode(struct udevice *bus, uint mode) return 0; } -static int ae3xx_spi_claim_bus(struct udevice *dev) +static int atcspi200_spi_claim_bus(struct udevice *dev) { struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); @@ -403,27 +403,27 @@ static int ae3xx_spi_claim_bus(struct udevice *dev) return -EINVAL; } - return __ae3xx_spi_claim_bus(ns); + return __atcspi200_spi_claim_bus(ns); } -static int ae3xx_spi_release_bus(struct udevice *dev) +static int atcspi200_spi_release_bus(struct udevice *dev) { struct nds_spi_slave *ns = dev_get_priv(dev->parent); - return __ae3xx_spi_release_bus(ns); + return __atcspi200_spi_release_bus(ns); } -static int ae3xx_spi_xfer(struct udevice *dev, unsigned int bitlen, +static int atcspi200_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); + return __atcspi200_spi_xfer(ns, bitlen, dout, din, flags); } -static int ae3xx_spi_get_clk(struct udevice *bus) +static int atcspi200_spi_get_clk(struct udevice *bus) { struct nds_spi_slave *ns = dev_get_priv(bus); struct clk clk; @@ -444,26 +444,26 @@ static int ae3xx_spi_get_clk(struct udevice *bus) return 0; } -static int ae3xx_spi_probe(struct udevice *bus) +static int atcspi200_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); + atcspi200_spi_get_clk(bus); return 0; } -static int ae3xx_ofdata_to_platadata(struct udevice *bus) +static int atcspi200_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), + sizeof(struct atcspi200_spi_regs), MAP_NOCACHE); if (!ns->regs) { printf("%s: could not map device address\n", __func__); @@ -474,26 +474,26 @@ static int ae3xx_ofdata_to_platadata(struct udevice *bus) 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 dm_spi_ops atcspi200_spi_ops = { + .claim_bus = atcspi200_spi_claim_bus, + .release_bus = atcspi200_spi_release_bus, + .xfer = atcspi200_spi_xfer, + .set_speed = atcspi200_spi_set_speed, + .set_mode = atcspi200_spi_set_mode, }; -static const struct udevice_id ae3xx_spi_ids[] = { +static const struct udevice_id atcspi200_spi_ids[] = { { .compatible = "andestech,atcspi200" }, { } }; -U_BOOT_DRIVER(ae3xx_spi) = { - .name = "ae3xx_spi", +U_BOOT_DRIVER(atcspi200_spi) = { + .name = "atcspi200_spi", .id = UCLASS_SPI, - .of_match = ae3xx_spi_ids, - .ops = &ae3xx_spi_ops, - .ofdata_to_platdata = ae3xx_ofdata_to_platadata, + .of_match = atcspi200_spi_ids, + .ops = &atcspi200_spi_ops, + .ofdata_to_platdata = atcspi200_ofdata_to_platadata, .priv_auto_alloc_size = sizeof(struct nds_spi_slave), - .probe = ae3xx_spi_probe, + .probe = atcspi200_spi_probe, }; #endif From 872cd42e706983b2efa928ec038f1f80d5eb5e87 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Wed, 15 Nov 2017 16:03:34 +0800 Subject: [PATCH 09/15] dt-bindings: spi: Add andestech atcspi200 spi binding doc Add a document to describe Andestech atcspi200 spi and binding information. Signed-off-by: Rick Chen --- .../spi/spi-atcspi200.txt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 doc/device-tree-bindings/spi/spi-atcspi200.txt diff --git a/doc/device-tree-bindings/spi/spi-atcspi200.txt b/doc/device-tree-bindings/spi/spi-atcspi200.txt new file mode 100644 index 0000000000..9c0630b500 --- /dev/null +++ b/doc/device-tree-bindings/spi/spi-atcspi200.txt @@ -0,0 +1,37 @@ +Andestech ATCSPI200 SPI controller Device Tree Bindings +------------------------------------------------------- +ATCSPI200 is a Serial Peripheral Interface (SPI) controller +which serves as a SPI master or a SPI slave. + +It is often be embedded in AE3XX and AE250 platforms. + +Required properties: +- compatible: has to be "andestech,atcspi200". +- reg: Base address and size of the controllers memory area. +- #address-cells: <1>, as required by generic SPI binding. +- #size-cells: <0>, also as required by generic SPI binding. +- interrupts: Property with a value describing the interrupt number. +- clocks: Clock phandles (see clock bindings for details). +- spi-max-frequency: Maximum SPI clocking speed of device in Hz. + +Optional properties: +- num-cs: Number of chip selects used. + +Example: + + 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; + }; + }; From 9f678ab139cd6ef0ab98759d63f1cee0fa534b66 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Tue, 14 Nov 2017 14:47:09 +0800 Subject: [PATCH 10/15] nds32: mmc: Support ftsdc010 DM. Add nds32_mmc to support ftsdc010 dm flow. Signed-off-by: Rick Chen --- drivers/mmc/Kconfig | 12 ++++ drivers/mmc/Makefile | 1 + drivers/mmc/nds32_mmc.c | 136 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 drivers/mmc/nds32_mmc.c diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 62ce0af7d3..8fbeaa740d 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -401,6 +401,18 @@ config STM32_SDMMC2 If you have a board based on such a SoC and with a SD/MMC slot, say Y or M here. +config MMC_NDS32 + bool "Andestech SD/MMC controller support" + depends on DM_MMC && OF_CONTROL && BLK && FTSDC010 + help + This enables support for the Andestech SD/MMM controller, which is + based on Faraday IP. + +config FTSDC010 + bool "Ftsdc010 SD/MMC controller Support" + help + This SD/MMC controller is present in Andestech SoCs which is based on Faraday IP. + endif config TEGRA124_MMC_DISABLE_EXT_LOOPBACK diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index d505f37f01..9af375b044 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_MMC_SANDBOX) += sandbox_mmc.o obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_SH_SDHI) += sh_sdhi.o obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o +obj-$(CONFIG_MMC_NDS32) += nds32_mmc.o # SDHCI obj-$(CONFIG_MMC_SDHCI) += sdhci.o diff --git a/drivers/mmc/nds32_mmc.c b/drivers/mmc/nds32_mmc.c new file mode 100644 index 0000000000..6d3c8572e5 --- /dev/null +++ b/drivers/mmc/nds32_mmc.c @@ -0,0 +1,136 @@ +/* + * Andestech ATFSDC010 SD/MMC driver + * + * (C) Copyright 2017 + * Rick Chen, NDS32 Software Engineering, rick@andestech.com + + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ftsdc010_mci.h" + +DECLARE_GLOBAL_DATA_PTR; + +#if CONFIG_IS_ENABLED(OF_PLATDATA) +struct nds_mmc { + fdt32_t bus_width; + bool cap_mmc_highspeed; + bool cap_sd_highspeed; + fdt32_t clock_freq_min_max[2]; + struct phandle_2_cell clocks[4]; + fdt32_t fifo_depth; + fdt32_t reg[2]; +}; +#endif + +struct nds_mmc_plat { +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct nds_mmc dtplat; +#endif + struct mmc_config cfg; + struct mmc mmc; +}; + +struct ftsdc_priv { + struct clk clk; + struct ftsdc010_chip chip; + int fifo_depth; + bool fifo_mode; + u32 minmax[2]; +}; + +static int nds32_mmc_ofdata_to_platdata(struct udevice *dev) +{ +#if !CONFIG_IS_ENABLED(OF_PLATDATA) + struct ftsdc_priv *priv = dev_get_priv(dev); + struct ftsdc010_chip *chip = &priv->chip; + chip->name = dev->name; + chip->ioaddr = (void *)devfdt_get_addr(dev); + chip->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "bus-width", 4); + chip->priv = dev; + priv->fifo_depth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "fifo-depth", 0); + priv->fifo_mode = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev), + "fifo-mode"); + if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), + "clock-freq-min-max", priv->minmax, 2)) { + int val = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "max-frequency", -EINVAL); + if (val < 0) + return val; + + priv->minmax[0] = 400000; /* 400 kHz */ + priv->minmax[1] = val; + } else { + debug("%s: 'clock-freq-min-max' property was deprecated.\n", + __func__); + } +#endif + chip->sclk = priv->minmax[1]; + chip->regs = chip->ioaddr; + return 0; +} + +static int nds32_mmc_probe(struct udevice *dev) +{ + struct nds_mmc_plat *plat = dev_get_platdata(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct ftsdc_priv *priv = dev_get_priv(dev); + struct ftsdc010_chip *chip = &priv->chip; + struct udevice *pwr_dev __maybe_unused; +#if CONFIG_IS_ENABLED(OF_PLATDATA) + int ret; + struct nds_mmc *dtplat = &plat->dtplat; + chip->name = dev->name; + chip->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]); + chip->buswidth = dtplat->bus_width; + chip->priv = dev; + chip->dev_index = 1; + memcpy(priv->minmax, dtplat->clock_freq_min_max, sizeof(priv->minmax)); + ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk); + if (ret < 0) + return ret; +#endif + ftsdc_setup_cfg(&plat->cfg, dev->name, chip->buswidth, chip->caps, + priv->minmax[1] , priv->minmax[0]); + chip->mmc = &plat->mmc; + chip->mmc->priv = &priv->chip; + chip->mmc->dev = dev; + upriv->mmc = chip->mmc; + return ftsdc010_probe(dev); +} + +static int nds32_mmc_bind(struct udevice *dev) +{ + struct nds_mmc_plat *plat = dev_get_platdata(dev); + return ftsdc010_bind(dev, &plat->mmc, &plat->cfg); +} + +static const struct udevice_id nds32_mmc_ids[] = { + { .compatible = "andestech,atsdc010" }, + { } +}; + +U_BOOT_DRIVER(nds32_mmc_drv) = { + .name = "nds32_mmc", + .id = UCLASS_MMC, + .of_match = nds32_mmc_ids, + .ofdata_to_platdata = nds32_mmc_ofdata_to_platdata, + .ops = &dm_ftsdc010_ops, + .bind = nds32_mmc_bind, + .probe = nds32_mmc_probe, + .priv_auto_alloc_size = sizeof(struct ftsdc_priv), + .platdata_auto_alloc_size = sizeof(struct nds_mmc_plat), +}; From 252185f22470d3bf828c7e989dfa06b83bb2e572 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Mon, 28 Aug 2017 16:44:11 +0800 Subject: [PATCH 11/15] nds32: ftsdc010: Support ftsdc010 DM. ftsdc010 support device tree flow. Signed-off-by: Rick Chen --- drivers/mmc/ftsdc010_mci.c | 145 ++++++++++++++++++++++++++++--------- drivers/mmc/ftsdc010_mci.h | 53 ++++++++++++++ 2 files changed, 164 insertions(+), 34 deletions(-) create mode 100644 drivers/mmc/ftsdc010_mci.h diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c index 652a718467..e044d8516a 100644 --- a/drivers/mmc/ftsdc010_mci.c +++ b/drivers/mmc/ftsdc010_mci.c @@ -12,24 +12,15 @@ #include #include -#include +#include #include #include #include +#include "ftsdc010_mci.h" #define CFG_CMD_TIMEOUT (CONFIG_SYS_HZ >> 4) /* 250 ms */ #define CFG_RST_TIMEOUT CONFIG_SYS_HZ /* 1 sec reset timeout */ -struct ftsdc010_chip { - void __iomem *regs; - uint32_t wprot; /* write protected (locked) */ - uint32_t rate; /* actual SD clock in Hz */ - uint32_t sclk; /* FTSDC010 source clock in Hz */ - uint32_t fifo; /* fifo depth in bytes */ - uint32_t acmd; - struct mmc_config cfg; /* mmc configuration */ -}; - static inline int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd) { struct ftsdc010_chip *chip = mmc->priv; @@ -127,9 +118,8 @@ static void ftsdc010_clkset(struct mmc *mmc, uint32_t rate) static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask) { int ret = -ETIMEDOUT; - uint32_t st, ts; - - for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) { + uint32_t st, timeout = 10000000; + while (timeout--) { st = readl(®s->status); if (!(st & mask)) continue; @@ -147,10 +137,16 @@ static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask) /* * u-boot mmc api */ - +#ifdef CONFIG_DM_MMC +static int ftsdc010_request(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); +#else static int ftsdc010_request(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { +#endif int ret = -EOPNOTSUPP; uint32_t len = 0; struct ftsdc010_chip *chip = mmc->priv; @@ -251,8 +247,14 @@ static int ftsdc010_request(struct mmc *mmc, struct mmc_cmd *cmd, return ret; } +#ifdef CONFIG_DM_MMC +static int ftsdc010_set_ios(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); +#else static int ftsdc010_set_ios(struct mmc *mmc) { +#endif struct ftsdc010_chip *chip = mmc->priv; struct ftsdc010_mmc __iomem *regs = chip->regs; @@ -274,20 +276,43 @@ static int ftsdc010_set_ios(struct mmc *mmc) return 0; } +#ifdef CONFIG_DM_MMC +static int ftsdc010_get_cd(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); +#else +static int ftsdc010_get_cd(struct mmc *mmc) +{ +#endif + struct ftsdc010_chip *chip = mmc->priv; + struct ftsdc010_mmc __iomem *regs = chip->regs; + return !(readl(®s->status) & FTSDC010_STATUS_CARD_DETECT); +} + +#ifdef CONFIG_DM_MMC +static int ftsdc010_get_wp(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); +#else +static int ftsdc010_get_wp(struct mmc *mmc) +{ +#endif + struct ftsdc010_chip *chip = mmc->priv; + struct ftsdc010_mmc __iomem *regs = chip->regs; + if (readl(®s->status) & FTSDC010_STATUS_WRITE_PROT) { + printf("ftsdc010: write protected\n"); + chip->wprot = 1; + } + + return 0; +} + static int ftsdc010_init(struct mmc *mmc) { struct ftsdc010_chip *chip = mmc->priv; struct ftsdc010_mmc __iomem *regs = chip->regs; uint32_t ts; - if (readl(®s->status) & FTSDC010_STATUS_CARD_DETECT) - return -ENOMEDIUM; - - if (readl(®s->status) & FTSDC010_STATUS_WRITE_PROT) { - printf("ftsdc010: write protected\n"); - chip->wprot = 1; - } - chip->fifo = (readl(®s->feature) & 0xff) << 2; /* 1. chip reset */ @@ -311,11 +336,70 @@ static int ftsdc010_init(struct mmc *mmc) return 0; } +#ifdef CONFIG_DM_MMC +int ftsdc010_probe(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + return ftsdc010_init(mmc); +} + +const struct dm_mmc_ops dm_ftsdc010_ops = { + .send_cmd = ftsdc010_request, + .set_ios = ftsdc010_set_ios, + .get_cd = ftsdc010_get_cd, + .get_wp = ftsdc010_get_wp, +}; + +#else static const struct mmc_ops ftsdc010_ops = { .send_cmd = ftsdc010_request, .set_ios = ftsdc010_set_ios, + .getcd = ftsdc010_get_cd, + .getwp = ftsdc010_get_wp, .init = ftsdc010_init, }; +#endif + +void ftsdc_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth, + uint caps, u32 max_clk, u32 min_clk) +{ + cfg->name = name; + cfg->f_min = min_clk; + cfg->f_max = max_clk; + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; + cfg->host_caps = caps; + if (buswidth == 8) { + cfg->host_caps |= MMC_MODE_8BIT; + cfg->host_caps &= ~MMC_MODE_4BIT; + } else { + cfg->host_caps |= MMC_MODE_4BIT; + cfg->host_caps &= ~MMC_MODE_8BIT; + } + cfg->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz; + cfg->part_type = PART_TYPE_DOS; + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; +} + +void set_bus_width(struct ftsdc010_mmc __iomem *regs, struct mmc_config *cfg) +{ + switch (readl(®s->bwr) & FTSDC010_BWR_CAPS_MASK) { + case FTSDC010_BWR_CAPS_4BIT: + cfg->host_caps |= MMC_MODE_4BIT; + break; + case FTSDC010_BWR_CAPS_8BIT: + cfg->host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT; + break; + default: + break; + } +} + +#ifdef CONFIG_BLK +int ftsdc010_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg) +{ + return mmc_bind(dev, mmc, cfg); +} +#else int ftsdc010_mmc_init(int devid) { @@ -345,19 +429,11 @@ int ftsdc010_mmc_init(int devid) #endif chip->cfg.name = "ftsdc010"; +#ifndef CONFIG_DM_MMC chip->cfg.ops = &ftsdc010_ops; +#endif chip->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz; - switch (readl(®s->bwr) & FTSDC010_BWR_CAPS_MASK) { - case FTSDC010_BWR_CAPS_4BIT: - chip->cfg.host_caps |= MMC_MODE_4BIT; - break; - case FTSDC010_BWR_CAPS_8BIT: - chip->cfg.host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT; - break; - default: - break; - } - + set_bus_width(regs , &chip->cfg); chip->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; chip->cfg.f_max = chip->sclk / 2; chip->cfg.f_min = chip->sclk / 0x100; @@ -373,3 +449,4 @@ int ftsdc010_mmc_init(int devid) return 0; } +#endif diff --git a/drivers/mmc/ftsdc010_mci.h b/drivers/mmc/ftsdc010_mci.h new file mode 100644 index 0000000000..31a27fd772 --- /dev/null +++ b/drivers/mmc/ftsdc010_mci.h @@ -0,0 +1,53 @@ +/* + * Faraday FTSDC010 Secure Digital Memory Card Host Controller + * + * Copyright (C) 2011 Andes Technology Corporation + * Macpaul Lin, Andes Technology Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include + +#ifndef __FTSDC010_MCI_H +#define __FTSDC010_MCI_H + +struct ftsdc010_chip { + void __iomem *regs; + uint32_t wprot; /* write protected (locked) */ + uint32_t rate; /* actual SD clock in Hz */ + uint32_t sclk; /* FTSDC010 source clock in Hz */ + uint32_t fifo; /* fifo depth in bytes */ + uint32_t acmd; + struct mmc_config cfg; /* mmc configuration */ + const char *name; + void *ioaddr; + unsigned int caps; + unsigned int version; + unsigned int clock; + unsigned int bus_hz; + unsigned int div; + int dev_index; + int dev_id; + int buswidth; + u32 fifoth_val; + struct mmc *mmc; + void *priv; + bool fifo_mode; +}; + + +#ifdef CONFIG_DM_MMC +/* Export the operations to drivers */ +int ftsdc010_probe(struct udevice *dev); +extern const struct dm_mmc_ops dm_ftsdc010_ops; +#endif +void ftsdc_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth, + uint caps, u32 max_clk, u32 min_clk); +void set_bus_width(struct ftsdc010_mmc __iomem *regs, struct mmc_config *cfg); + +#ifdef CONFIG_BLK +int ftsdc010_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg); +#endif + + +#endif /* __FTSDC010_MCI_H */ From febcd97699e7cdd7904c98a8993c619972557125 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 1 Jun 2017 15:09:25 +0800 Subject: [PATCH 12/15] nds32: dts: Support ftsdc010 DM. Add dts to support ftsdc010 dm flow on AG101P/AE3XX platform. Signed-off-by: Rick Chen --- arch/nds32/dts/ae3xx.dts | 8 ++++++++ arch/nds32/dts/ag101p.dts | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/arch/nds32/dts/ae3xx.dts b/arch/nds32/dts/ae3xx.dts index fbe6d74437..b19ba988db 100644 --- a/arch/nds32/dts/ae3xx.dts +++ b/arch/nds32/dts/ae3xx.dts @@ -69,6 +69,14 @@ interrupts = <25 4>; }; + mmc0: mmc@f0e00000 { + compatible = "andestech,atsdc010"; + max-frequency = <100000000>; + fifo-depth = <0x10>; + reg = <0xf0e00000 0x1000>; + interrupts = <17 4>; + }; + nor@0,0 { compatible = "cfi-flash"; reg = <0x88000000 0x1000>; diff --git a/arch/nds32/dts/ag101p.dts b/arch/nds32/dts/ag101p.dts index 99cde2f8b8..19dc36fa15 100644 --- a/arch/nds32/dts/ag101p.dts +++ b/arch/nds32/dts/ag101p.dts @@ -60,4 +60,12 @@ reg = <0x90900000 0x1000>; interrupts = <25 4>; }; + + mmc0: mmc@98e00000 { + compatible = "andestech,atsdc010"; + max-frequency = <30000000>; + fifo-depth = <0x10>; + reg = <0x98e00000 0x1000>; + interrupts = <5 4>; + }; }; From c39b79df43dcabc19a87bbea7e64a26670c73f44 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Mon, 28 Aug 2017 16:17:13 +0800 Subject: [PATCH 13/15] nds32: board: Support ftsdc010 DM. AG101P/AE3XX enable ftsdc010 dm flow. Signed-off-by: Rick Chen --- board/AndesTech/adp-ag101p/adp-ag101p.c | 2 ++ configs/adp-ae3xx_defconfig | 3 +++ configs/adp-ag101p_defconfig | 3 +++ include/configs/adp-ae3xx.h | 1 - include/configs/adp-ag101p.h | 1 - 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/board/AndesTech/adp-ag101p/adp-ag101p.c b/board/AndesTech/adp-ag101p/adp-ag101p.c index 79608f4efe..f918c630c1 100644 --- a/board/AndesTech/adp-ag101p/adp-ag101p.c +++ b/board/AndesTech/adp-ag101p/adp-ag101p.c @@ -85,8 +85,10 @@ ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info) int board_mmc_init(bd_t *bis) { +#ifndef CONFIG_DM_MMC #ifdef CONFIG_FTSDC010 ftsdc010_mmc_init(0); +#endif #endif return 0; } diff --git a/configs/adp-ae3xx_defconfig b/configs/adp-ae3xx_defconfig index 38696e6f40..600566955a 100644 --- a/configs/adp-ae3xx_defconfig +++ b/configs/adp-ae3xx_defconfig @@ -27,6 +27,9 @@ CONFIG_CFI_FLASH=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_DM_MMC=y +CONFIG_MMC_NDS32=y +CONFIG_FTSDC010=y CONFIG_DM_ETH=y CONFIG_FTMAC100=y CONFIG_BAUDRATE=38400 diff --git a/configs/adp-ag101p_defconfig b/configs/adp-ag101p_defconfig index 5cf2d26552..82cf7f2481 100644 --- a/configs/adp-ag101p_defconfig +++ b/configs/adp-ag101p_defconfig @@ -18,6 +18,9 @@ CONFIG_ENV_IS_IN_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y CONFIG_MMC=y +CONFIG_DM_MMC=y +CONFIG_MMC_NDS32=y +CONFIG_FTSDC010=y CONFIG_MTD_NOR_FLASH=y CONFIG_DM_ETH=y CONFIG_FTMAC100=y diff --git a/include/configs/adp-ae3xx.h b/include/configs/adp-ae3xx.h index 6946029333..5644a6153b 100644 --- a/include/configs/adp-ae3xx.h +++ b/include/configs/adp-ae3xx.h @@ -91,7 +91,6 @@ /* * SD (MMC) controller */ -#define CONFIG_FTSDC010 #define CONFIG_FTSDC010_NUMBER 1 #define CONFIG_FTSDC010_SDIO diff --git a/include/configs/adp-ag101p.h b/include/configs/adp-ag101p.h index fad4d308e0..f2de384631 100644 --- a/include/configs/adp-ag101p.h +++ b/include/configs/adp-ag101p.h @@ -97,7 +97,6 @@ /* * SD (MMC) controller */ -#define CONFIG_FTSDC010 #define CONFIG_FTSDC010_NUMBER 1 #define CONFIG_FTSDC010_SDIO From 1a9db640b4f5f8070d75a5baf794678625b4f9a0 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Fri, 25 Aug 2017 14:02:13 +0800 Subject: [PATCH 14/15] nds32: ftsdc010: fix wait status error coding. Bit of DATA_END and DATA_CRC_OK shall be checked for returning pass or fail of a request. Signed-off-by: Rick Chen --- drivers/mmc/ftsdc010_mci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c index e044d8516a..113cf13909 100644 --- a/drivers/mmc/ftsdc010_mci.c +++ b/drivers/mmc/ftsdc010_mci.c @@ -128,8 +128,9 @@ static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask) break; } - if (ret) + if (ret){ debug("ftsdc010: wait st(0x%x) timeout\n", mask); + } return ret; } @@ -241,7 +242,7 @@ static int ftsdc010_request(struct mmc *mmc, struct mmc_cmd *cmd, if (!ret) { ret = ftsdc010_wait(regs, - FTSDC010_STATUS_DATA_END | FTSDC010_STATUS_DATA_ERROR); + FTSDC010_STATUS_DATA_END | FTSDC010_STATUS_DATA_CRC_OK); } return ret; From 73cd56b2df213c629191139e5c6705e069b6214f Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Fri, 25 Aug 2017 14:03:00 +0800 Subject: [PATCH 15/15] nds32: ftsdc010: Fix SD detech fail on AE3XX. AE3XX can not support SD high-speed mode. SW can work-around by removing HS capibility. Signed-off-by: Rick Chen --- drivers/mmc/ftsdc010_mci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c index 113cf13909..6ac4f83bd1 100644 --- a/drivers/mmc/ftsdc010_mci.c +++ b/drivers/mmc/ftsdc010_mci.c @@ -376,7 +376,6 @@ void ftsdc_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth, cfg->host_caps |= MMC_MODE_4BIT; cfg->host_caps &= ~MMC_MODE_8BIT; } - cfg->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz; cfg->part_type = PART_TYPE_DOS; cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; }