diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dma/ti/Kconfig | 4 | ||||
-rw-r--r-- | drivers/dma/ti/Makefile | 4 | ||||
-rw-r--r-- | drivers/dma/ti/k3-psil-am654.c | 89 | ||||
-rw-r--r-- | drivers/dma/ti/k3-psil-j721e.c | 47 | ||||
-rw-r--r-- | drivers/dma/ti/k3-psil-priv.h | 43 | ||||
-rw-r--r-- | drivers/dma/ti/k3-psil.c | 42 | ||||
-rw-r--r-- | drivers/dma/ti/k3-psil.h | 67 | ||||
-rw-r--r-- | drivers/dma/ti/k3-udma.c | 402 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 5 | ||||
-rw-r--r-- | drivers/mmc/mmc_spi.c | 52 | ||||
-rw-r--r-- | drivers/mmc/omap_hsmmc.c | 2 | ||||
-rw-r--r-- | drivers/net/ti/am65-cpsw-nuss.c | 15 | ||||
-rw-r--r-- | drivers/soc/ti/k3-navss-ringacc.c | 161 |
13 files changed, 693 insertions, 240 deletions
diff --git a/drivers/dma/ti/Kconfig b/drivers/dma/ti/Kconfig index 3d5498326c..9cbd5f334d 100644 --- a/drivers/dma/ti/Kconfig +++ b/drivers/dma/ti/Kconfig @@ -8,7 +8,11 @@ config TI_K3_NAVSS_UDMA select DMA select TI_K3_NAVSS_RINGACC select TI_K3_NAVSS_PSILCFG + select TI_K3_PSIL default n help Support for UDMA used in K3 devices. endif + +config TI_K3_PSIL + bool diff --git a/drivers/dma/ti/Makefile b/drivers/dma/ti/Makefile index de2f9ac91a..4ea9c626cc 100644 --- a/drivers/dma/ti/Makefile +++ b/drivers/dma/ti/Makefile @@ -1,3 +1,7 @@ # SPDX-License-Identifier: GPL-2.0+ obj-$(CONFIG_TI_K3_NAVSS_UDMA) += k3-udma.o +obj-$(CONFIG_TI_K3_PSIL) += k3-psil-data.o +k3-psil-data-y += k3-psil.o +k3-psil-data-$(CONFIG_SOC_K3_AM6) += k3-psil-am654.o +k3-psil-data-$(CONFIG_SOC_K3_J721E) += k3-psil-j721e.o diff --git a/drivers/dma/ti/k3-psil-am654.c b/drivers/dma/ti/k3-psil-am654.c new file mode 100644 index 0000000000..f95d99cfd3 --- /dev/null +++ b/drivers/dma/ti/k3-psil-am654.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com + * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> + */ + +#include <linux/kernel.h> + +#include "k3-psil-priv.h" + +#define PSIL_ETHERNET(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_NATIVE, \ + .pkt_mode = 1, \ + .needs_epib = 1, \ + .psd_size = 16, \ + }, \ + } + +/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */ +static struct psil_ep am654_src_ep_map[] = { + /* PRU_ICSSG0 */ + PSIL_ETHERNET(0x4100), + PSIL_ETHERNET(0x4101), + PSIL_ETHERNET(0x4102), + PSIL_ETHERNET(0x4103), + /* PRU_ICSSG1 */ + PSIL_ETHERNET(0x4200), + PSIL_ETHERNET(0x4201), + PSIL_ETHERNET(0x4202), + PSIL_ETHERNET(0x4203), + /* PRU_ICSSG2 */ + PSIL_ETHERNET(0x4300), + PSIL_ETHERNET(0x4301), + PSIL_ETHERNET(0x4302), + PSIL_ETHERNET(0x4303), + /* CPSW0 */ + PSIL_ETHERNET(0x7000), +}; + +/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */ +static struct psil_ep am654_dst_ep_map[] = { + /* PRU_ICSSG0 */ + PSIL_ETHERNET(0xc100), + PSIL_ETHERNET(0xc101), + PSIL_ETHERNET(0xc102), + PSIL_ETHERNET(0xc103), + PSIL_ETHERNET(0xc104), + PSIL_ETHERNET(0xc105), + PSIL_ETHERNET(0xc106), + PSIL_ETHERNET(0xc107), + /* PRU_ICSSG1 */ + PSIL_ETHERNET(0xc200), + PSIL_ETHERNET(0xc201), + PSIL_ETHERNET(0xc202), + PSIL_ETHERNET(0xc203), + PSIL_ETHERNET(0xc204), + PSIL_ETHERNET(0xc205), + PSIL_ETHERNET(0xc206), + PSIL_ETHERNET(0xc207), + /* PRU_ICSSG2 */ + PSIL_ETHERNET(0xc300), + PSIL_ETHERNET(0xc301), + PSIL_ETHERNET(0xc302), + PSIL_ETHERNET(0xc303), + PSIL_ETHERNET(0xc304), + PSIL_ETHERNET(0xc305), + PSIL_ETHERNET(0xc306), + PSIL_ETHERNET(0xc307), + /* CPSW0 */ + PSIL_ETHERNET(0xf000), + PSIL_ETHERNET(0xf001), + PSIL_ETHERNET(0xf002), + PSIL_ETHERNET(0xf003), + PSIL_ETHERNET(0xf004), + PSIL_ETHERNET(0xf005), + PSIL_ETHERNET(0xf006), + PSIL_ETHERNET(0xf007), +}; + +struct psil_ep_map am654_ep_map = { + .name = "am654", + .src = am654_src_ep_map, + .src_count = ARRAY_SIZE(am654_src_ep_map), + .dst = am654_dst_ep_map, + .dst_count = ARRAY_SIZE(am654_dst_ep_map), +}; diff --git a/drivers/dma/ti/k3-psil-j721e.c b/drivers/dma/ti/k3-psil-j721e.c new file mode 100644 index 0000000000..105ffd946f --- /dev/null +++ b/drivers/dma/ti/k3-psil-j721e.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com + * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> + */ + +#include <linux/kernel.h> + +#include "k3-psil-priv.h" + +#define PSIL_ETHERNET(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_NATIVE, \ + .pkt_mode = 1, \ + .needs_epib = 1, \ + .psd_size = 16, \ + }, \ + } + +/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */ +static struct psil_ep j721e_src_ep_map[] = { + /* CPSW0 */ + PSIL_ETHERNET(0x7000), +}; + +/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */ +static struct psil_ep j721e_dst_ep_map[] = { + /* CPSW0 */ + PSIL_ETHERNET(0xf000), + PSIL_ETHERNET(0xf001), + PSIL_ETHERNET(0xf002), + PSIL_ETHERNET(0xf003), + PSIL_ETHERNET(0xf004), + PSIL_ETHERNET(0xf005), + PSIL_ETHERNET(0xf006), + PSIL_ETHERNET(0xf007), +}; + +struct psil_ep_map j721e_ep_map = { + .name = "j721e", + .src = j721e_src_ep_map, + .src_count = ARRAY_SIZE(j721e_src_ep_map), + .dst = j721e_dst_ep_map, + .dst_count = ARRAY_SIZE(j721e_dst_ep_map), +}; diff --git a/drivers/dma/ti/k3-psil-priv.h b/drivers/dma/ti/k3-psil-priv.h new file mode 100644 index 0000000000..d3a38322b1 --- /dev/null +++ b/drivers/dma/ti/k3-psil-priv.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com + */ + +#ifndef K3_PSIL_PRIV_H_ +#define K3_PSIL_PRIV_H_ + +#include "k3-psil.h" + +struct psil_ep { + u32 thread_id; + struct psil_endpoint_config ep_config; +}; + +/** + * struct psil_ep_map - PSI-L thread ID configuration maps + * @name: Name of the map, set it to the name of the SoC + * @src: Array of source PSI-L thread configurations + * @src_count: Number of entries in the src array + * @dst: Array of destination PSI-L thread configurations + * @dst_count: Number of entries in the dst array + * + * In case of symmetric configuration for a matching src/dst thread (for example + * 0x4400 and 0xc400) only the src configuration can be present. If no dst + * configuration found the code will look for (dst_thread_id & ~0x8000) to find + * the symmetric match. + */ +struct psil_ep_map { + char *name; + struct psil_ep *src; + int src_count; + struct psil_ep *dst; + int dst_count; +}; + +struct psil_endpoint_config *psil_get_ep_config(u32 thread_id); + +/* SoC PSI-L endpoint maps */ +extern struct psil_ep_map am654_ep_map; +extern struct psil_ep_map j721e_ep_map; + +#endif /* K3_PSIL_PRIV_H_ */ diff --git a/drivers/dma/ti/k3-psil.c b/drivers/dma/ti/k3-psil.c new file mode 100644 index 0000000000..b5c92b2829 --- /dev/null +++ b/drivers/dma/ti/k3-psil.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com + * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> + */ + +#include <linux/kernel.h> +#include <linux/err.h> + +#include "k3-psil-priv.h" + +static const struct psil_ep_map *soc_ep_map; + +struct psil_endpoint_config *psil_get_ep_config(u32 thread_id) +{ + int i; + + if (!soc_ep_map) { + if (IS_ENABLED(CONFIG_SOC_K3_AM6)) + soc_ep_map = &am654_ep_map; + else if (IS_ENABLED(CONFIG_SOC_K3_J721E)) + soc_ep_map = &j721e_ep_map; + } + + if (thread_id & K3_PSIL_DST_THREAD_ID_OFFSET && soc_ep_map->dst) { + /* check in destination thread map */ + for (i = 0; i < soc_ep_map->dst_count; i++) { + if (soc_ep_map->dst[i].thread_id == thread_id) + return &soc_ep_map->dst[i].ep_config; + } + } + + thread_id &= ~K3_PSIL_DST_THREAD_ID_OFFSET; + if (soc_ep_map->src) { + for (i = 0; i < soc_ep_map->src_count; i++) { + if (soc_ep_map->src[i].thread_id == thread_id) + return &soc_ep_map->src[i].ep_config; + } + } + + return ERR_PTR(-ENOENT); +} diff --git a/drivers/dma/ti/k3-psil.h b/drivers/dma/ti/k3-psil.h new file mode 100644 index 0000000000..53c61b4595 --- /dev/null +++ b/drivers/dma/ti/k3-psil.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com + */ + +#ifndef K3_PSIL_H_ +#define K3_PSIL_H_ + +#include <linux/types.h> + +#define K3_PSIL_DST_THREAD_ID_OFFSET 0x8000 + +struct device; + +/** + * enum udma_tp_level - Channel Throughput Levels + * @UDMA_TP_NORMAL: Normal channel + * @UDMA_TP_HIGH: High Throughput channel + * @UDMA_TP_ULTRAHIGH: Ultra High Throughput channel + */ +enum udma_tp_level { + UDMA_TP_NORMAL = 0, + UDMA_TP_HIGH, + UDMA_TP_ULTRAHIGH, + UDMA_TP_LAST, +}; + +/** + * enum psil_endpoint_type - PSI-L Endpoint type + * @PSIL_EP_NATIVE: Normal channel + * @PSIL_EP_PDMA_XY: XY mode PDMA + * @PSIL_EP_PDMA_MCAN: MCAN mode PDMA + * @PSIL_EP_PDMA_AASRC: AASRC mode PDMA + */ +enum psil_endpoint_type { + PSIL_EP_NATIVE = 0, + PSIL_EP_PDMA_XY, + PSIL_EP_PDMA_MCAN, + PSIL_EP_PDMA_AASRC, +}; + +/** + * struct psil_endpoint_config - PSI-L Endpoint configuration + * @ep_type: PSI-L endpoint type + * @pkt_mode: If set, the channel must be in Packet mode, otherwise in + * TR mode + * @notdpkt: TDCM must be suppressed on the TX channel + * @needs_epib: Endpoint needs EPIB + * @psd_size: If set, PSdata is used by the endpoint + * @channel_tpl: Desired throughput level for the channel + * @pdma_acc32: ACC32 must be enabled on the PDMA side + * @pdma_burst: BURST must be enabled on the PDMA side + */ +struct psil_endpoint_config { + enum psil_endpoint_type ep_type; + + unsigned pkt_mode:1; + unsigned notdpkt:1; + unsigned needs_epib:1; + u32 psd_size; + enum udma_tp_level channel_tpl; + + /* PDMA properties, valid for PSIL_EP_PDMA_* */ + unsigned pdma_acc32:1; + unsigned pdma_burst:1; +}; +#endif /* K3_PSIL_H_ */ diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index 2ce16c8e27..57d9fbfabb 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -22,7 +22,6 @@ #include <dma.h> #include <dma-uclass.h> #include <linux/delay.h> -#include <dt-bindings/dma/k3-udma.h> #include <linux/bitmap.h> #include <linux/err.h> #include <linux/soc/ti/k3-navss-ringacc.h> @@ -31,12 +30,7 @@ #include <linux/soc/ti/ti_sci_protocol.h> #include "k3-udma-hwdef.h" - -#if BITS_PER_LONG == 64 -#define RINGACC_RING_USE_PROXY (0) -#else -#define RINGACC_RING_USE_PROXY (1) -#endif +#include "k3-psil-priv.h" #define K3_UDMA_MAX_RFLOWS 1024 @@ -65,12 +59,28 @@ struct udma_rchan { void __iomem *reg_rt; int id; - struct k3_nav_ring *fd_ring; /* Free Descriptor ring */ - struct k3_nav_ring *r_ring; /* Receive ring*/ +}; + +#define UDMA_FLAG_PDMA_ACC32 BIT(0) +#define UDMA_FLAG_PDMA_BURST BIT(1) +#define UDMA_FLAG_TDTYPE BIT(2) + +struct udma_match_data { + u32 psil_base; + bool enable_memcpy_support; + u32 flags; + u32 statictr_z_mask; + u32 rchan_oes_offset; + + u8 tpl_levels; + u32 level_start_idx[]; }; struct udma_rflow { int id; + + struct k3_nav_ring *fd_ring; /* Free Descriptor ring */ + struct k3_nav_ring *r_ring; /* Receive ring*/ }; enum udma_rm_range { @@ -114,12 +124,34 @@ struct udma_dev { struct udma_rchan *rchans; struct udma_rflow *rflows; + struct udma_match_data *match_data; + struct udma_chan *channels; u32 psil_base; u32 ch_count; }; +struct udma_chan_config { + u32 psd_size; /* size of Protocol Specific Data */ + u32 metadata_size; /* (needs_epib ? 16:0) + psd_size */ + u32 hdesc_size; /* Size of a packet descriptor in packet mode */ + int remote_thread_id; + u32 atype; + u32 src_thread; + u32 dst_thread; + enum psil_endpoint_type ep_type; + enum udma_tp_level channel_tpl; /* Channel Throughput Level */ + + enum dma_direction dir; + + unsigned int pkt_mode:1; /* TR or packet */ + unsigned int needs_epib:1; /* EPIB is needed for the communication or not */ + unsigned int enable_acc32:1; + unsigned int enable_burst:1; + unsigned int notdpkt:1; /* Suppress sending TDC packet */ +}; + struct udma_chan { struct udma_dev *ud; char name[20]; @@ -132,20 +164,11 @@ struct udma_chan { u32 bcnt; /* number of bytes completed since the start of the channel */ - bool pkt_mode; /* TR or packet */ - bool needs_epib; /* EPIB is needed for the communication or not */ - u32 psd_size; /* size of Protocol Specific Data */ - u32 metadata_size; /* (needs_epib ? 16:0) + psd_size */ - int slave_thread_id; - u32 src_thread; - u32 dst_thread; - u32 static_tr_type; + struct udma_chan_config config; u32 id; - enum dma_direction dir; struct cppi5_host_desc_t *desc_tx; - u32 hdesc_size; bool in_use; void *desc_rx; u32 num_rx_bufs; @@ -271,7 +294,7 @@ static inline bool udma_is_chan_running(struct udma_chan *uc) u32 trt_ctl = 0; u32 rrt_ctl = 0; - switch (uc->dir) { + switch (uc->config.dir) { case DMA_DEV_TO_MEM: rrt_ctl = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_CTL_REG); pr_debug("%s: rrt_ctl: 0x%08x (peer: 0x%08x)\n", @@ -305,9 +328,9 @@ static int udma_pop_from_ring(struct udma_chan *uc, dma_addr_t *addr) struct k3_nav_ring *ring = NULL; int ret = -ENOENT; - switch (uc->dir) { + switch (uc->config.dir) { case DMA_DEV_TO_MEM: - ring = uc->rchan->r_ring; + ring = uc->rflow->r_ring; break; case DMA_MEM_TO_DEV: ring = uc->tchan->tc_ring; @@ -330,10 +353,10 @@ static void udma_reset_rings(struct udma_chan *uc) struct k3_nav_ring *ring1 = NULL; struct k3_nav_ring *ring2 = NULL; - switch (uc->dir) { + switch (uc->config.dir) { case DMA_DEV_TO_MEM: - ring1 = uc->rchan->fd_ring; - ring2 = uc->rchan->r_ring; + ring1 = uc->rflow->fd_ring; + ring2 = uc->rflow->r_ring; break; case DMA_MEM_TO_DEV: ring1 = uc->tchan->t_ring; @@ -392,7 +415,7 @@ static inline int udma_stop_hard(struct udma_chan *uc) { pr_debug("%s: ENTER (chan%d)\n", __func__, uc->id); - switch (uc->dir) { + switch (uc->config.dir) { case DMA_DEV_TO_MEM: udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG, 0); udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, 0); @@ -418,9 +441,8 @@ static int udma_start(struct udma_chan *uc) if (udma_is_chan_running(uc)) goto out; - pr_debug("%s: chan:%d dir:%s (static_tr_type: %d)\n", - __func__, uc->id, udma_get_dir_text(uc->dir), - uc->static_tr_type); + pr_debug("%s: chan:%d dir:%s\n", + __func__, uc->id, udma_get_dir_text(uc->config.dir)); /* Make sure that we clear the teardown bit, if it is set */ udma_stop_hard(uc); @@ -428,7 +450,7 @@ static int udma_start(struct udma_chan *uc) /* Reset all counters */ udma_reset_counters(uc); - switch (uc->dir) { + switch (uc->config.dir) { case DMA_DEV_TO_MEM: udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, UDMA_CHAN_RT_CTL_EN); @@ -530,10 +552,10 @@ static inline void udma_stop_dev2mem(struct udma_chan *uc, bool sync) static inline int udma_stop(struct udma_chan *uc) { pr_debug("%s: chan:%d dir:%s\n", - __func__, uc->id, udma_get_dir_text(uc->dir)); + __func__, uc->id, udma_get_dir_text(uc->config.dir)); udma_reset_counters(uc); - switch (uc->dir) { + switch (uc->config.dir) { case DMA_DEV_TO_MEM: udma_stop_dev2mem(uc, true); break; @@ -768,21 +790,14 @@ static int udma_alloc_tx_resources(struct udma_chan *uc) if (ret) return ret; - uc->tchan->t_ring = k3_nav_ringacc_request_ring( - ud->ringacc, uc->tchan->id, - RINGACC_RING_USE_PROXY); - if (!uc->tchan->t_ring) { + ret = k3_nav_ringacc_request_rings_pair(ud->ringacc, uc->tchan->id, -1, + &uc->tchan->t_ring, + &uc->tchan->tc_ring); + if (ret) { ret = -EBUSY; goto err_tx_ring; } - uc->tchan->tc_ring = k3_nav_ringacc_request_ring( - ud->ringacc, -1, RINGACC_RING_USE_PROXY); - if (!uc->tchan->tc_ring) { - ret = -EBUSY; - goto err_txc_ring; - } - memset(&ring_cfg, 0, sizeof(ring_cfg)); ring_cfg.size = 16; ring_cfg.elm_size = K3_NAV_RINGACC_RING_ELSIZE_8; @@ -799,7 +814,6 @@ static int udma_alloc_tx_resources(struct udma_chan *uc) err_ringcfg: k3_nav_ringacc_ring_free(uc->tchan->tc_ring); uc->tchan->tc_ring = NULL; -err_txc_ring: k3_nav_ringacc_ring_free(uc->tchan->t_ring); uc->tchan->t_ring = NULL; err_tx_ring: @@ -813,12 +827,15 @@ static void udma_free_rx_resources(struct udma_chan *uc) if (!uc->rchan) return; - k3_nav_ringacc_ring_free(uc->rchan->fd_ring); - k3_nav_ringacc_ring_free(uc->rchan->r_ring); - uc->rchan->fd_ring = NULL; - uc->rchan->r_ring = NULL; + if (uc->rflow) { + k3_nav_ringacc_ring_free(uc->rflow->fd_ring); + k3_nav_ringacc_ring_free(uc->rflow->r_ring); + uc->rflow->fd_ring = NULL; + uc->rflow->r_ring = NULL; + + udma_put_rflow(uc); + } - udma_put_rflow(uc); udma_put_rchan(uc); } @@ -826,6 +843,7 @@ static int udma_alloc_rx_resources(struct udma_chan *uc) { struct k3_nav_ring_cfg ring_cfg; struct udma_dev *ud = uc->ud; + struct udma_rflow *rflow; int fd_ring_id; int ret; @@ -834,7 +852,7 @@ static int udma_alloc_rx_resources(struct udma_chan *uc) return ret; /* For MEM_TO_MEM we don't need rflow or rings */ - if (uc->dir == DMA_MEM_TO_MEM) + if (uc->config.dir == DMA_MEM_TO_MEM) return 0; ret = udma_get_rflow(uc, uc->rchan->id); @@ -845,40 +863,31 @@ static int udma_alloc_rx_resources(struct udma_chan *uc) fd_ring_id = ud->tchan_cnt + ud->echan_cnt + uc->rchan->id; - uc->rchan->fd_ring = k3_nav_ringacc_request_ring( - ud->ringacc, fd_ring_id, - RINGACC_RING_USE_PROXY); - if (!uc->rchan->fd_ring) { + rflow = uc->rflow; + ret = k3_nav_ringacc_request_rings_pair(ud->ringacc, fd_ring_id, -1, + &rflow->fd_ring, &rflow->r_ring); + if (ret) { ret = -EBUSY; goto err_rx_ring; } - uc->rchan->r_ring = k3_nav_ringacc_request_ring( - ud->ringacc, -1, RINGACC_RING_USE_PROXY); - if (!uc->rchan->r_ring) { - ret = -EBUSY; - goto err_rxc_ring; - } - memset(&ring_cfg, 0, sizeof(ring_cfg)); ring_cfg.size = 16; ring_cfg.elm_size = K3_NAV_RINGACC_RING_ELSIZE_8; ring_cfg.mode = K3_NAV_RINGACC_RING_MODE_RING; - ret = k3_nav_ringacc_ring_cfg(uc->rchan->fd_ring, &ring_cfg); - ret |= k3_nav_ringacc_ring_cfg(uc->rchan->r_ring, &ring_cfg); - + ret = k3_nav_ringacc_ring_cfg(rflow->fd_ring, &ring_cfg); + ret |= k3_nav_ringacc_ring_cfg(rflow->r_ring, &ring_cfg); if (ret) goto err_ringcfg; return 0; err_ringcfg: - k3_nav_ringacc_ring_free(uc->rchan->r_ring); - uc->rchan->r_ring = NULL; -err_rxc_ring: - k3_nav_ringacc_ring_free(uc->rchan->fd_ring); - uc->rchan->fd_ring = NULL; + k3_nav_ringacc_ring_free(rflow->r_ring); + rflow->r_ring = NULL; + k3_nav_ringacc_ring_free(rflow->fd_ring); + rflow->fd_ring = NULL; err_rx_ring: udma_put_rflow(uc); err_rflow: @@ -896,7 +905,7 @@ static int udma_alloc_tchan_sci_req(struct udma_chan *uc) u32 mode; int ret; - if (uc->pkt_mode) + if (uc->config.pkt_mode) mode = TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR; else mode = TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR; @@ -907,11 +916,11 @@ static int udma_alloc_tchan_sci_req(struct udma_chan *uc) req.nav_id = tisci_rm->tisci_dev_id; req.index = uc->tchan->id; req.tx_chan_type = mode; - if (uc->dir == DMA_MEM_TO_MEM) + if (uc->config.dir == DMA_MEM_TO_MEM) req.tx_fetch_size = sizeof(struct cppi5_desc_hdr_t) >> 2; else - req.tx_fetch_size = cppi5_hdesc_calc_size(uc->needs_epib, - uc->psd_size, + req.tx_fetch_size = cppi5_hdesc_calc_size(uc->config.needs_epib, + uc->config.psd_size, 0) >> 2; req.txcq_qnum = tc_ring; @@ -925,8 +934,8 @@ static int udma_alloc_tchan_sci_req(struct udma_chan *uc) static int udma_alloc_rchan_sci_req(struct udma_chan *uc) { struct udma_dev *ud = uc->ud; - int fd_ring = k3_nav_ringacc_get_ring_id(uc->rchan->fd_ring); - int rx_ring = k3_nav_ringacc_get_ring_id(uc->rchan->r_ring); + int fd_ring = k3_nav_ringacc_get_ring_id(uc->rflow->fd_ring); + int rx_ring = k3_nav_ringacc_get_ring_id(uc->rflow->r_ring); int tc_ring = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring); struct ti_sci_msg_rm_udmap_rx_ch_cfg req = { 0 }; struct ti_sci_msg_rm_udmap_flow_cfg flow_req = { 0 }; @@ -934,7 +943,7 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc) u32 mode; int ret; - if (uc->pkt_mode) + if (uc->config.pkt_mode) mode = TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR; else mode = TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR; @@ -947,16 +956,16 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc) req.nav_id = tisci_rm->tisci_dev_id; req.index = uc->rchan->id; req.rx_chan_type = mode; - if (uc->dir == DMA_MEM_TO_MEM) { + if (uc->config.dir == DMA_MEM_TO_MEM) { req.rx_fetch_size = sizeof(struct cppi5_desc_hdr_t) >> 2; req.rxcq_qnum = tc_ring; } else { - req.rx_fetch_size = cppi5_hdesc_calc_size(uc->needs_epib, - uc->psd_size, + req.rx_fetch_size = cppi5_hdesc_calc_size(uc->config.needs_epib, + uc->config.psd_size, 0) >> 2; req.rxcq_qnum = rx_ring; } - if (uc->rflow->id != uc->rchan->id && uc->dir != DMA_MEM_TO_MEM) { + if (uc->rflow->id != uc->rchan->id && uc->config.dir != DMA_MEM_TO_MEM) { req.flowid_start = uc->rflow->id; req.flowid_cnt = 1; } @@ -967,7 +976,7 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc) uc->rchan->id, ret); return ret; } - if (uc->dir == DMA_MEM_TO_MEM) + if (uc->config.dir == DMA_MEM_TO_MEM) return ret; flow_req.valid_params = @@ -989,12 +998,12 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc) flow_req.nav_id = tisci_rm->tisci_dev_id; flow_req.flow_index = uc->rflow->id; - if (uc->needs_epib) + if (uc->config.needs_epib) flow_req.rx_einfo_present = 1; else flow_req.rx_einfo_present = 0; - if (uc->psd_size) + if (uc->config.psd_size) flow_req.rx_psinfo_present = 1; else flow_req.rx_psinfo_present = 0; @@ -1027,11 +1036,12 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) int ret; pr_debug("%s: chan:%d as %s\n", - __func__, uc->id, udma_get_dir_text(uc->dir)); + __func__, uc->id, udma_get_dir_text(uc->config.dir)); - switch (uc->dir) { + switch (uc->config.dir) { case DMA_MEM_TO_MEM: /* Non synchronized - mem to mem type of transfer */ + uc->config.pkt_mode = false; ret = udma_get_chan_pair(uc); if (ret) return ret; @@ -1044,8 +1054,8 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) if (ret) goto err_free_res; - uc->src_thread = ud->psil_base + uc->tchan->id; - uc->dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000; + uc->config.src_thread = ud->psil_base + uc->tchan->id; + uc->config.dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000; break; case DMA_MEM_TO_DEV: /* Slave transfer synchronized - mem to dev (TX) trasnfer */ @@ -1053,10 +1063,9 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) if (ret) goto err_free_res; - uc->src_thread = ud->psil_base + uc->tchan->id; - uc->dst_thread = uc->slave_thread_id; - if (!(uc->dst_thread & 0x8000)) - uc->dst_thread |= 0x8000; + uc->config.src_thread = ud->psil_base + uc->tchan->id; + uc->config.dst_thread = uc->config.remote_thread_id; + uc->config.dst_thread |= 0x8000; break; case DMA_DEV_TO_MEM: @@ -1065,19 +1074,19 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) if (ret) goto err_free_res; - uc->src_thread = uc->slave_thread_id; - uc->dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000; + uc->config.src_thread = uc->config.remote_thread_id; + uc->config.dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000; break; default: /* Can not happen */ pr_debug("%s: chan:%d invalid direction (%u)\n", - __func__, uc->id, uc->dir); + __func__, uc->id, uc->config.dir); return -EINVAL; } /* We have channel indexes and rings */ - if (uc->dir == DMA_MEM_TO_MEM) { + if (uc->config.dir == DMA_MEM_TO_MEM) { ret = udma_alloc_tchan_sci_req(uc); if (ret) goto err_free_res; @@ -1087,7 +1096,7 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) goto err_free_res; } else { /* Slave transfer */ - if (uc->dir == DMA_MEM_TO_DEV) { + if (uc->config.dir == DMA_MEM_TO_DEV) { ret = udma_alloc_tchan_sci_req(uc); if (ret) goto err_free_res; @@ -1108,7 +1117,7 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) } /* PSI-L pairing */ - ret = udma_navss_psil_pair(ud, uc->src_thread, uc->dst_thread); + ret = udma_navss_psil_pair(ud, uc->config.src_thread, uc->config.dst_thread); if (ret) { dev_err(ud->dev, "k3_nav_psil_request_link fail\n"); goto err_free_res; @@ -1119,7 +1128,7 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) err_free_res: udma_free_tx_resources(uc); udma_free_rx_resources(uc); - uc->slave_thread_id = -1; + uc->config.remote_thread_id = -1; return ret; } @@ -1128,15 +1137,15 @@ static void udma_free_chan_resources(struct udma_chan *uc) /* Some configuration to UDMA-P channel: disable, reset, whatever */ /* Release PSI-L pairing */ - udma_navss_psil_unpair(uc->ud, uc->src_thread, uc->dst_thread); + udma_navss_psil_unpair(uc->ud, uc->config.src_thread, uc->config.dst_thread); /* Reset the rings for a new start */ udma_reset_rings(uc); udma_free_tx_resources(uc); udma_free_rx_resources(uc); - uc->slave_thread_id = -1; - uc->dir = DMA_MEM_TO_MEM; + uc->config.remote_thread_id = -1; + uc->config.dir = DMA_MEM_TO_MEM; } static int udma_get_mmrs(struct udevice *dev) @@ -1293,12 +1302,8 @@ static int udma_probe(struct udevice *dev) if (IS_ERR(ud->ringacc)) return PTR_ERR(ud->ringacc); - ud->psil_base = dev_read_u32_default(dev, "ti,psil-base", 0); - if (!ud->psil_base) { - dev_info(dev, - "Missing ti,psil-base property, using %d.\n", ret); - return -EINVAL; - } + ud->match_data = (void *)dev_get_driver_data(dev); + ud->psil_base = ud->match_data->psil_base; ret = uclass_get_device_by_phandle(UCLASS_FIRMWARE, dev, "ti,sci", &tisci_dev); @@ -1364,10 +1369,10 @@ static int udma_probe(struct udevice *dev) uc->ud = ud; uc->id = i; - uc->slave_thread_id = -1; + uc->config.remote_thread_id = -1; uc->tchan = NULL; uc->rchan = NULL; - uc->dir = DMA_MEM_TO_MEM; + uc->config.dir = DMA_MEM_TO_MEM; sprintf(uc->name, "UDMA chan%d\n", i); if (!i) uc->in_use = true; @@ -1514,6 +1519,7 @@ static int udma_transfer(struct udevice *dev, int direction, static int udma_request(struct dma *dma) { struct udma_dev *ud = dev_get_priv(dma->dev); + struct udma_chan_config *ucc; struct udma_chan *uc; unsigned long dummy; int ret; @@ -1524,30 +1530,27 @@ static int udma_request(struct dma *dma) } uc = &ud->channels[dma->id]; + ucc = &uc->config; ret = udma_alloc_chan_resources(uc); if (ret) { dev_err(dma->dev, "alloc dma res failed %d\n", ret); return -EINVAL; } - uc->hdesc_size = cppi5_hdesc_calc_size(uc->needs_epib, - uc->psd_size, 0); - uc->hdesc_size = ALIGN(uc->hdesc_size, ARCH_DMA_MINALIGN); - - if (uc->dir == DMA_MEM_TO_DEV) { - uc->desc_tx = dma_alloc_coherent(uc->hdesc_size, &dummy); - memset(uc->desc_tx, 0, uc->hdesc_size); + if (uc->config.dir == DMA_MEM_TO_DEV) { + uc->desc_tx = dma_alloc_coherent(ucc->hdesc_size, &dummy); + memset(uc->desc_tx, 0, ucc->hdesc_size); } else { uc->desc_rx = dma_alloc_coherent( - uc->hdesc_size * UDMA_RX_DESC_NUM, &dummy); - memset(uc->desc_rx, 0, uc->hdesc_size * UDMA_RX_DESC_NUM); + ucc->hdesc_size * UDMA_RX_DESC_NUM, &dummy); + memset(uc->desc_rx, 0, ucc->hdesc_size * UDMA_RX_DESC_NUM); } uc->in_use = true; uc->desc_rx_cur = 0; uc->num_rx_bufs = 0; - if (uc->dir == DMA_DEV_TO_MEM) { + if (uc->config.dir == DMA_DEV_TO_MEM) { uc->cfg_data.flow_id_base = uc->rflow->id; uc->cfg_data.flow_id_cnt = 1; } @@ -1632,7 +1635,7 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata) } uc = &ud->channels[dma->id]; - if (uc->dir != DMA_MEM_TO_DEV) + if (uc->config.dir != DMA_MEM_TO_DEV) return -EINVAL; tc_ring_id = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring); @@ -1642,8 +1645,8 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata) cppi5_hdesc_reset_hbdesc(desc_tx); cppi5_hdesc_init(desc_tx, - uc->needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0, - uc->psd_size); + uc->config.needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0, + uc->config.psd_size); cppi5_hdesc_set_pktlen(desc_tx, len); cppi5_hdesc_attach_buf(desc_tx, dma_src, len, dma_src, len); cppi5_desc_set_pktids(&desc_tx->hdr, uc->id, 0x3fff); @@ -1656,7 +1659,7 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata) ALIGN((unsigned long)dma_src + len, ARCH_DMA_MINALIGN)); flush_dcache_range((unsigned long)desc_tx, - ALIGN((unsigned long)desc_tx + uc->hdesc_size, + ALIGN((unsigned long)desc_tx + uc->config.hdesc_size, ARCH_DMA_MINALIGN)); ret = udma_push_to_ring(uc->tchan->t_ring, uc->desc_tx); @@ -1674,6 +1677,7 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata) static int udma_receive(struct dma *dma, void **dst, void *metadata) { struct udma_dev *ud = dev_get_priv(dma->dev); + struct udma_chan_config *ucc; struct cppi5_host_desc_t *desc_rx; dma_addr_t buf_dma; struct udma_chan *uc; @@ -1686,13 +1690,14 @@ static int udma_receive(struct dma *dma, void **dst, void *metadata) return -EINVAL; } uc = &ud->channels[dma->id]; + ucc = &uc->config; - if (uc->dir != DMA_DEV_TO_MEM) + if (uc->config.dir != DMA_DEV_TO_MEM) return -EINVAL; if (!uc->num_rx_bufs) return -EINVAL; - ret = k3_nav_ringacc_ring_pop(uc->rchan->r_ring, &desc_rx); + ret = k3_nav_ringacc_ring_pop(uc->rflow->r_ring, &desc_rx); if (ret && ret != -ENODATA) { dev_err(dma->dev, "rx dma fail ch_id:%lu %d\n", dma->id, ret); return ret; @@ -1702,7 +1707,7 @@ static int udma_receive(struct dma *dma, void **dst, void *metadata) /* invalidate cache data */ invalidate_dcache_range((ulong)desc_rx, - (ulong)(desc_rx + uc->hdesc_size)); + (ulong)(desc_rx + ucc->hdesc_size)); cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len); pkt_len = cppi5_hdesc_get_pktlen(desc_rx); @@ -1721,10 +1726,10 @@ static int udma_receive(struct dma *dma, void **dst, void *metadata) static int udma_of_xlate(struct dma *dma, struct ofnode_phandle_args *args) { + struct udma_chan_config *ucc; struct udma_dev *ud = dev_get_priv(dma->dev); struct udma_chan *uc = &ud->channels[0]; - ofnode chconf_node, slave_node; - char prop[50]; + struct psil_endpoint_config *ep_config; u32 val; for (val = 0; val < ud->ch_count; val++) { @@ -1736,48 +1741,40 @@ static int udma_of_xlate(struct dma *dma, struct ofnode_phandle_args *args) if (val == ud->ch_count) return -EBUSY; - uc->dir = DMA_DEV_TO_MEM; - if (args->args[2] == UDMA_DIR_TX) - uc->dir = DMA_MEM_TO_DEV; - - slave_node = ofnode_get_by_phandle(args->args[0]); - if (!ofnode_valid(slave_node)) { - dev_err(ud->dev, "slave node is missing\n"); - return -EINVAL; - } - - snprintf(prop, sizeof(prop), "ti,psil-config%u", args->args[1]); - chconf_node = ofnode_find_subnode(slave_node, prop); - if (!ofnode_valid(chconf_node)) { - dev_err(ud->dev, "Channel configuration node is missing\n"); - return -EINVAL; - } + ucc = &uc->config; + ucc->remote_thread_id = args->args[0]; + if (ucc->remote_thread_id & K3_PSIL_DST_THREAD_ID_OFFSET) + ucc->dir = DMA_MEM_TO_DEV; + else + ucc->dir = DMA_DEV_TO_MEM; - if (!ofnode_read_u32(chconf_node, "linux,udma-mode", &val)) { - if (val == UDMA_PKT_MODE) - uc->pkt_mode = true; + ep_config = psil_get_ep_config(ucc->remote_thread_id); + if (IS_ERR(ep_config)) { + dev_err(ud->dev, "No configuration for psi-l thread 0x%04x\n", + uc->config.remote_thread_id); + ucc->dir = DMA_MEM_TO_MEM; + ucc->remote_thread_id = -1; + return false; } - if (!ofnode_read_u32(chconf_node, "statictr-type", &val)) - uc->static_tr_type = val; + ucc->pkt_mode = ep_config->pkt_mode; + ucc->channel_tpl = ep_config->channel_tpl; + ucc->notdpkt = ep_config->notdpkt; + ucc->ep_type = ep_config->ep_type; - uc->needs_epib = ofnode_read_bool(chconf_node, "ti,needs-epib"); - if (!ofnode_read_u32(chconf_node, "ti,psd-size", &val)) - uc->psd_size = val; - uc->metadata_size = (uc->needs_epib ? 16 : 0) + uc->psd_size; + ucc->needs_epib = ep_config->needs_epib; + ucc->psd_size = ep_config->psd_size; + ucc->metadata_size = (ucc->needs_epib ? CPPI5_INFO0_HDESC_EPIB_SIZE : 0) + ucc->psd_size; - if (ofnode_read_u32(slave_node, "ti,psil-base", &val)) { - dev_err(ud->dev, "ti,psil-base is missing\n"); - return -EINVAL; - } - - uc->slave_thread_id = val + args->args[1]; + ucc->hdesc_size = cppi5_hdesc_calc_size(ucc->needs_epib, + ucc->psd_size, 0); + ucc->hdesc_size = ALIGN(ucc->hdesc_size, ARCH_DMA_MINALIGN); dma->id = uc->id; pr_debug("Allocated dma chn:%lu epib:%d psdata:%u meta:%u thread_id:%x\n", - dma->id, uc->needs_epib, - uc->psd_size, uc->metadata_size, - uc->slave_thread_id); + dma->id, ucc->needs_epib, + ucc->psd_size, ucc->metadata_size, + ucc->remote_thread_id); return 0; } @@ -1796,29 +1793,29 @@ int udma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size) } uc = &ud->channels[dma->id]; - if (uc->dir != DMA_DEV_TO_MEM) + if (uc->config.dir != DMA_DEV_TO_MEM) return -EINVAL; if (uc->num_rx_bufs >= UDMA_RX_DESC_NUM) return -EINVAL; desc_num = uc->desc_rx_cur % UDMA_RX_DESC_NUM; - desc_rx = uc->desc_rx + (desc_num * uc->hdesc_size); + desc_rx = uc->desc_rx + (desc_num * uc->config.hdesc_size); dma_dst = (dma_addr_t)dst; cppi5_hdesc_reset_hbdesc(desc_rx); cppi5_hdesc_init(desc_rx, - uc->needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0, - uc->psd_size); + uc->config.needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0, + uc->config.psd_size); cppi5_hdesc_set_pktlen(desc_rx, size); cppi5_hdesc_attach_buf(desc_rx, dma_dst, size, dma_dst, size); flush_dcache_range((unsigned long)desc_rx, - ALIGN((unsigned long)desc_rx + uc->hdesc_size, + ALIGN((unsigned long)desc_rx + uc->config.hdesc_size, ARCH_DMA_MINALIGN)); - udma_push_to_ring(uc->rchan->fd_ring, desc_rx); + udma_push_to_ring(uc->rflow->fd_ring, desc_rx); uc->num_rx_bufs++; uc->desc_rx_cur++; @@ -1859,10 +1856,73 @@ static const struct dma_ops udma_ops = { .get_cfg = udma_get_cfg, }; +static struct udma_match_data am654_main_data = { + .psil_base = 0x1000, + .enable_memcpy_support = true, + .statictr_z_mask = GENMASK(11, 0), + .rchan_oes_offset = 0x200, + .tpl_levels = 2, + .level_start_idx = { + [0] = 8, /* Normal channels */ + [1] = 0, /* High Throughput channels */ + }, +}; + +static struct udma_match_data am654_mcu_data = { + .psil_base = 0x6000, + .enable_memcpy_support = true, + .statictr_z_mask = GENMASK(11, 0), + .rchan_oes_offset = 0x200, + .tpl_levels = 2, + .level_start_idx = { + [0] = 2, /* Normal channels */ + [1] = 0, /* High Throughput channels */ + }, +}; + +static struct udma_match_data j721e_main_data = { + .psil_base = 0x1000, + .enable_memcpy_support = true, + .flags = UDMA_FLAG_PDMA_ACC32 | UDMA_FLAG_PDMA_BURST | UDMA_FLAG_TDTYPE, + .statictr_z_mask = GENMASK(23, 0), + .rchan_oes_offset = 0x400, + .tpl_levels = 3, + .level_start_idx = { + [0] = 16, /* Normal channels */ + [1] = 4, /* High Throughput channels */ + [2] = 0, /* Ultra High Throughput channels */ + }, +}; + +static struct udma_match_data j721e_mcu_data = { + .psil_base = 0x6000, + .enable_memcpy_support = true, + .flags = UDMA_FLAG_PDMA_ACC32 | UDMA_FLAG_PDMA_BURST | UDMA_FLAG_TDTYPE, + .statictr_z_mask = GENMASK(23, 0), + .rchan_oes_offset = 0x400, + .tpl_levels = 2, + .level_start_idx = { + [0] = 2, /* Normal channels */ + [1] = 0, /* High Throughput channels */ + }, +}; + static const struct udevice_id udma_ids[] = { - { .compatible = "ti,k3-navss-udmap" }, - { .compatible = "ti,j721e-navss-mcu-udmap" }, - { } + { + .compatible = "ti,am654-navss-main-udmap", + .data = (ulong)&am654_main_data, + }, + { + .compatible = "ti,am654-navss-mcu-udmap", + .data = (ulong)&am654_mcu_data, + }, { + .compatible = "ti,j721e-navss-main-udmap", + .data = (ulong)&j721e_main_data, + }, { + .compatible = "ti,j721e-navss-mcu-udmap", + .data = (ulong)&j721e_mcu_data, + }, + { /* Sentinel */ }, }; U_BOOT_DRIVER(ti_edma3) = { diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 50f47d4ba2..7b5c55be7d 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1753,6 +1753,11 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) mmc_set_bus_width(mmc, 1); mmc_select_mode(mmc, MMC_LEGACY); mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE); +#if CONFIG_IS_ENABLED(MMC_WRITE) + err = sd_read_ssr(mmc); + if (err) + pr_warn("unable to read ssr\n"); +#endif return 0; } diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c index e76ab54838..50fcd32674 100644 --- a/drivers/mmc/mmc_spi.c +++ b/drivers/mmc/mmc_spi.c @@ -59,6 +59,7 @@ #define CMD_TIMEOUT 8 #define READ_TIMEOUT 3000000 /* 1 sec */ #define WRITE_TIMEOUT 3000000 /* 1 sec */ +#define R1B_TIMEOUT 3000000 /* 1 sec */ struct mmc_spi_plat { struct mmc_config cfg; @@ -72,7 +73,7 @@ struct mmc_spi_priv { static int mmc_spi_sendcmd(struct udevice *dev, ushort cmdidx, u32 cmdarg, u32 resp_type, u8 *resp, u32 resp_size, - bool resp_match, u8 resp_match_value) + bool resp_match, u8 resp_match_value, bool r1b) { int i, rpos = 0, ret = 0; u8 cmdo[7], r; @@ -105,12 +106,14 @@ static int mmc_spi_sendcmd(struct udevice *dev, if (resp_match) { r = ~resp_match_value; i = CMD_TIMEOUT; - while (i--) { + while (i) { ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0); if (ret) return ret; debug(" resp%d=0x%x", rpos, r); rpos++; + i--; + if (r == resp_match_value) break; } @@ -131,6 +134,24 @@ static int mmc_spi_sendcmd(struct udevice *dev, resp[i] = r; } + if (r1b == true) { + i = R1B_TIMEOUT; + while (i) { + ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0); + if (ret) + return ret; + + debug(" resp%d=0x%x", rpos, r); + rpos++; + i--; + + if (r) + break; + } + if (!i) + return -ETIMEDOUT; + } + debug("\n"); return 0; @@ -263,8 +284,8 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd, int i, multi, ret = 0; u8 *resp = NULL; u32 resp_size = 0; - bool resp_match = false; - u8 resp8 = 0, resp40[5] = { 0 }, resp_match_value = 0; + bool resp_match = false, r1b = false; + u8 resp8 = 0, resp16[2] = { 0 }, resp40[5] = { 0 }, resp_match_value = 0; dm_spi_claim_bus(dev); @@ -289,20 +310,33 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd, resp_size = sizeof(resp40); break; case MMC_CMD_SEND_STATUS: + resp = (u8 *)&resp16[0]; + resp_size = sizeof(resp16); + break; case MMC_CMD_SET_BLOCKLEN: case MMC_CMD_SPI_CRC_ON_OFF: - case MMC_CMD_STOP_TRANSMISSION: resp = &resp8; resp_size = sizeof(resp8); resp_match = true; resp_match_value = 0x0; break; + case MMC_CMD_STOP_TRANSMISSION: + case MMC_CMD_ERASE: + resp = &resp8; + resp_size = sizeof(resp8); + r1b = true; + break; case MMC_CMD_SEND_CSD: case MMC_CMD_SEND_CID: case MMC_CMD_READ_SINGLE_BLOCK: case MMC_CMD_READ_MULTIPLE_BLOCK: case MMC_CMD_WRITE_SINGLE_BLOCK: case MMC_CMD_WRITE_MULTIPLE_BLOCK: + case MMC_CMD_APP_CMD: + case SD_CMD_ERASE_WR_BLK_START: + case SD_CMD_ERASE_WR_BLK_END: + resp = &resp8; + resp_size = sizeof(resp8); break; default: resp = &resp8; @@ -313,7 +347,7 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd, }; ret = mmc_spi_sendcmd(dev, cmd->cmdidx, cmd->cmdarg, cmd->resp_type, - resp, resp_size, resp_match, resp_match_value); + resp, resp_size, resp_match, resp_match_value, r1b); if (ret) goto done; @@ -330,8 +364,10 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd, cmd->response[0] |= (uint)resp40[1] << 24; break; case MMC_CMD_SEND_STATUS: - cmd->response[0] = (resp8 & 0xff) ? - MMC_STATUS_ERROR : MMC_STATUS_RDY_FOR_DATA; + if (resp16[0] || resp16[1]) + cmd->response[0] = MMC_STATUS_ERROR; + else + cmd->response[0] = MMC_STATUS_RDY_FOR_DATA; break; case MMC_CMD_SEND_CID: case MMC_CMD_SEND_CSD: diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 0e05fe4cfc..db1f85125f 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -843,7 +843,7 @@ static int omap_hsmmc_init_setup(struct mmc *mmc) omap_hsmmc_conf_bus_power(mmc, (reg_val & VS33_3V3SUP) ? MMC_SIGNAL_VOLTAGE_330 : MMC_SIGNAL_VOLTAGE_180); #else - writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl); + writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V3, &mmc_base->hctl); writel(readl(&mmc_base->capa) | VS33_3V3SUP | VS18_1V8SUP, &mmc_base->capa); #endif diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c index 85f3e49c05..971bdcdfda 100644 --- a/drivers/net/ti/am65-cpsw-nuss.c +++ b/drivers/net/ti/am65-cpsw-nuss.c @@ -61,6 +61,9 @@ #define AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD 0x3 #define AM65_CPSW_ALE_PN_CTL_REG_MAC_ONLY BIT(11) +#define AM65_CPSW_ALE_THREADMAPDEF_REG 0x134 +#define AM65_CPSW_ALE_DEFTHREAD_EN BIT(15) + #define AM65_CPSW_MACSL_CTL_REG 0x0 #define AM65_CPSW_MACSL_CTL_REG_IFCTL_A BIT(15) #define AM65_CPSW_MACSL_CTL_EXT_EN BIT(18) @@ -364,6 +367,9 @@ static int am65_cpsw_start(struct udevice *dev) writel(AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0)); + writel(AM65_CPSW_ALE_DEFTHREAD_EN, + common->ale_base + AM65_CPSW_ALE_THREADMAPDEF_REG); + /* PORT x configuration */ /* Port x Max length register */ @@ -680,7 +686,7 @@ static int am65_cpsw_probe_cpsw(struct udevice *dev) AM65_CPSW_CPSW_NU_ALE_BASE; cpsw_common->mdio_base = cpsw_common->ss_base + AM65_CPSW_MDIO_BASE; - ports_np = dev_read_subnode(dev, "ports"); + ports_np = dev_read_subnode(dev, "ethernet-ports"); if (!ofnode_valid(ports_np)) { ret = -ENOENT; goto out; @@ -746,13 +752,6 @@ static int am65_cpsw_probe_cpsw(struct udevice *dev) goto out; } - node = dev_read_subnode(dev, "mdio"); - if (!ofnode_valid(node)) { - dev_err(dev, "can't find mdio\n"); - ret = -ENOENT; - goto out; - } - cpsw_common->bus_freq = dev_read_u32_default(dev, "bus_freq", AM65_CPSW_MDIO_BUS_FREQ_DEF); diff --git a/drivers/soc/ti/k3-navss-ringacc.c b/drivers/soc/ti/k3-navss-ringacc.c index ecc4b8b5a0..c48e9befe4 100644 --- a/drivers/soc/ti/k3-navss-ringacc.c +++ b/drivers/soc/ti/k3-navss-ringacc.c @@ -127,6 +127,22 @@ struct k3_nav_ring_ops { }; /** + * struct k3_nav_ring_state - Internal state tracking structure + * + * @free: Number of free entries + * @occ: Occupancy + * @windex: Write index + * @rindex: Read index + */ +struct k3_nav_ring_state { + u32 free; + u32 occ; + u32 windex; + u32 rindex; + u32 tdown_complete:1; +}; + +/** * struct k3_nav_ring - RA Ring descriptor * * @rt - Ring control/status registers @@ -139,10 +155,6 @@ struct k3_nav_ring_ops { * @elm_size - Size of the ring element * @mode - Ring mode * @flags - flags - * @free - Number of free elements - * @occ - Ring occupancy - * @windex - Write index (only for @K3_NAV_RINGACC_RING_MODE_RING) - * @rindex - Read index (only for @K3_NAV_RINGACC_RING_MODE_RING) * @ring_id - Ring Id * @parent - Pointer on struct @k3_nav_ringacc * @use_count - Use count for shared rings @@ -161,16 +173,17 @@ struct k3_nav_ring { u32 flags; #define KNAV_RING_FLAG_BUSY BIT(1) #define K3_NAV_RING_FLAG_SHARED BIT(2) - u32 free; - u32 occ; - u32 windex; - u32 rindex; + struct k3_nav_ring_state state; u32 ring_id; struct k3_nav_ringacc *parent; u32 use_count; int proxy_id; }; +struct k3_nav_ringacc_ops { + int (*init)(struct udevice *dev, struct k3_nav_ringacc *ringacc); +}; + /** * struct k3_nav_ringacc - Rings accelerator descriptor * @@ -186,6 +199,7 @@ struct k3_nav_ring { * @tisci - pointer ti-sci handle * @tisci_ring_ops - ti-sci rings ops * @tisci_dev_id - ti-sci device id + * @ops: SoC specific ringacc operation */ struct k3_nav_ringacc { struct udevice *dev; @@ -204,6 +218,8 @@ struct k3_nav_ringacc { const struct ti_sci_handle *tisci; const struct ti_sci_rm_ringacc_ops *tisci_ring_ops; u32 tisci_dev_id; + + const struct k3_nav_ringacc_ops *ops; }; static long k3_nav_ringacc_ring_get_fifo_pos(struct k3_nav_ring *ring) @@ -312,6 +328,29 @@ error: return NULL; } +int k3_nav_ringacc_request_rings_pair(struct k3_nav_ringacc *ringacc, + int fwd_id, int compl_id, + struct k3_nav_ring **fwd_ring, + struct k3_nav_ring **compl_ring) +{ + int ret = 0; + + if (!fwd_ring || !compl_ring) + return -EINVAL; + + *fwd_ring = k3_nav_ringacc_request_ring(ringacc, fwd_id, 0); + if (!(*fwd_ring)) + return -ENODEV; + + *compl_ring = k3_nav_ringacc_request_ring(ringacc, compl_id, 0); + if (!(*compl_ring)) { + k3_nav_ringacc_ring_free(*fwd_ring); + ret = -ENODEV; + } + + return ret; +} + static void k3_ringacc_ring_reset_sci(struct k3_nav_ring *ring) { struct k3_nav_ringacc *ringacc = ring->parent; @@ -338,10 +377,7 @@ void k3_nav_ringacc_ring_reset(struct k3_nav_ring *ring) if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) return; - ring->occ = 0; - ring->free = 0; - ring->rindex = 0; - ring->windex = 0; + memset(&ring->state, 0, sizeof(ring->state)); k3_ringacc_ring_reset_sci(ring); } @@ -546,10 +582,7 @@ int k3_nav_ringacc_ring_cfg(struct k3_nav_ring *ring, ring->size = cfg->size; ring->elm_size = cfg->elm_size; ring->mode = cfg->mode; - ring->occ = 0; - ring->free = 0; - ring->rindex = 0; - ring->windex = 0; + memset(&ring->state, 0, sizeof(ring->state)); if (ring->proxy_id != K3_RINGACC_PROXY_NOT_USED) ring->proxy = ringacc->proxy_target_base + @@ -625,10 +658,10 @@ u32 k3_nav_ringacc_ring_get_free(struct k3_nav_ring *ring) if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) return -EINVAL; - if (!ring->free) - ring->free = ring->size - ringacc_readl(&ring->rt->occ); + if (!ring->state.free) + ring->state.free = ring->size - ringacc_readl(&ring->rt->occ); - return ring->free; + return ring->state.free; } u32 k3_nav_ringacc_ring_get_occ(struct k3_nav_ring *ring) @@ -694,21 +727,21 @@ static int k3_nav_ringacc_ring_access_proxy( pr_debug("proxy:memcpy_fromio(x): --> ptr(%p), mode:%d\n", ptr, access_mode); memcpy_fromio(elem, ptr, (4 << ring->elm_size)); - ring->occ--; + ring->state.occ--; break; case K3_RINGACC_ACCESS_MODE_PUSH_TAIL: case K3_RINGACC_ACCESS_MODE_PUSH_HEAD: pr_debug("proxy:memcpy_toio(x): --> ptr(%p), mode:%d\n", ptr, access_mode); memcpy_toio(ptr, elem, (4 << ring->elm_size)); - ring->free--; + ring->state.free--; break; default: return -EINVAL; } pr_debug("proxy: free%d occ%d\n", - ring->free, ring->occ); + ring->state.free, ring->state.occ); return 0; } @@ -763,21 +796,21 @@ static int k3_nav_ringacc_ring_access_io( pr_debug("memcpy_fromio(x): --> ptr(%p), mode:%d\n", ptr, access_mode); memcpy_fromio(elem, ptr, (4 << ring->elm_size)); - ring->occ--; + ring->state.occ--; break; case K3_RINGACC_ACCESS_MODE_PUSH_TAIL: case K3_RINGACC_ACCESS_MODE_PUSH_HEAD: pr_debug("memcpy_toio(x): --> ptr(%p), mode:%d\n", ptr, access_mode); memcpy_toio(ptr, elem, (4 << ring->elm_size)); - ring->free--; + ring->state.free--; break; default: return -EINVAL; } pr_debug("free%d index%d occ%d index%d\n", - ring->free, ring->windex, ring->occ, ring->rindex); + ring->state.free, ring->state.windex, ring->state.occ, ring->state.rindex); return 0; } @@ -810,7 +843,7 @@ static int k3_nav_ringacc_ring_push_mem(struct k3_nav_ring *ring, void *elem) { void *elem_ptr; - elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->windex); + elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->state.windex); memcpy(elem_ptr, elem, (4 << ring->elm_size)); @@ -819,12 +852,12 @@ static int k3_nav_ringacc_ring_push_mem(struct k3_nav_ring *ring, void *elem) ring->size * (4 << ring->elm_size), ARCH_DMA_MINALIGN)); - ring->windex = (ring->windex + 1) % ring->size; - ring->free--; + ring->state.windex = (ring->state.windex + 1) % ring->size; + ring->state.free--; ringacc_writel(1, &ring->rt->db); pr_debug("ring_push_mem: free%d index%d\n", - ring->free, ring->windex); + ring->state.free, ring->state.windex); return 0; } @@ -833,7 +866,7 @@ static int k3_nav_ringacc_ring_pop_mem(struct k3_nav_ring *ring, void *elem) { void *elem_ptr; - elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->rindex); + elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->state.rindex); invalidate_dcache_range((unsigned long)ring->ring_mem_virt, ALIGN((unsigned long)ring->ring_mem_virt + @@ -842,12 +875,12 @@ static int k3_nav_ringacc_ring_pop_mem(struct k3_nav_ring *ring, void *elem) memcpy(elem, elem_ptr, (4 << ring->elm_size)); - ring->rindex = (ring->rindex + 1) % ring->size; - ring->occ--; + ring->state.rindex = (ring->state.rindex + 1) % ring->size; + ring->state.occ--; ringacc_writel(-1, &ring->rt->db); pr_debug("ring_pop_mem: occ%d index%d pos_ptr%p\n", - ring->occ, ring->rindex, elem_ptr); + ring->state.occ, ring->state.rindex, elem_ptr); return 0; } @@ -859,7 +892,7 @@ int k3_nav_ringacc_ring_push(struct k3_nav_ring *ring, void *elem) return -EINVAL; pr_debug("ring_push%d: free%d index%d\n", - ring->ring_id, ring->free, ring->windex); + ring->ring_id, ring->state.free, ring->state.windex); if (k3_nav_ringacc_ring_is_full(ring)) return -ENOMEM; @@ -878,7 +911,7 @@ int k3_nav_ringacc_ring_push_head(struct k3_nav_ring *ring, void *elem) return -EINVAL; pr_debug("ring_push_head: free%d index%d\n", - ring->free, ring->windex); + ring->state.free, ring->state.windex); if (k3_nav_ringacc_ring_is_full(ring)) return -ENOMEM; @@ -896,13 +929,13 @@ int k3_nav_ringacc_ring_pop(struct k3_nav_ring *ring, void *elem) if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) return -EINVAL; - if (!ring->occ) - ring->occ = k3_nav_ringacc_ring_get_occ(ring); + if (!ring->state.occ) + ring->state.occ = k3_nav_ringacc_ring_get_occ(ring); pr_debug("ring_pop%d: occ%d index%d\n", - ring->ring_id, ring->occ, ring->rindex); + ring->ring_id, ring->state.occ, ring->state.rindex); - if (!ring->occ) + if (!ring->state.occ && !ring->state.tdown_complete) return -ENODATA; if (ring->ops && ring->ops->pop_head) @@ -918,13 +951,13 @@ int k3_nav_ringacc_ring_pop_tail(struct k3_nav_ring *ring, void *elem) if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) return -EINVAL; - if (!ring->occ) - ring->occ = k3_nav_ringacc_ring_get_occ(ring); + if (!ring->state.occ) + ring->state.occ = k3_nav_ringacc_ring_get_occ(ring); pr_debug("ring_pop_tail: occ%d index%d\n", - ring->occ, ring->rindex); + ring->state.occ, ring->state.rindex); - if (!ring->occ) + if (!ring->state.occ) return -ENODATA; if (ring->ops && ring->ops->pop_tail) @@ -982,18 +1015,11 @@ static int k3_nav_ringacc_probe_dt(struct k3_nav_ringacc *ringacc) return 0; } -static int k3_nav_ringacc_probe(struct udevice *dev) +static int k3_nav_ringacc_init(struct udevice *dev, struct k3_nav_ringacc *ringacc) { - struct k3_nav_ringacc *ringacc; void __iomem *base_fifo, *base_rt; int ret, i; - ringacc = dev_get_priv(dev); - if (!ringacc) - return -ENOMEM; - - ringacc->dev = dev; - ret = k3_nav_ringacc_probe_dt(ringacc); if (ret) return ret; @@ -1063,11 +1089,42 @@ static int k3_nav_ringacc_probe(struct udevice *dev) return 0; } +struct ringacc_match_data { + struct k3_nav_ringacc_ops ops; +}; + +static struct ringacc_match_data k3_nav_ringacc_data = { + .ops = { + .init = k3_nav_ringacc_init, + }, +}; + static const struct udevice_id knav_ringacc_ids[] = { - { .compatible = "ti,am654-navss-ringacc" }, + { .compatible = "ti,am654-navss-ringacc", .data = (ulong)&k3_nav_ringacc_data, }, {}, }; +static int k3_nav_ringacc_probe(struct udevice *dev) +{ + struct k3_nav_ringacc *ringacc; + int ret; + const struct ringacc_match_data *match_data; + + match_data = (struct ringacc_match_data *)dev_get_driver_data(dev); + + ringacc = dev_get_priv(dev); + if (!ringacc) + return -ENOMEM; + + ringacc->dev = dev; + ringacc->ops = &match_data->ops; + ret = ringacc->ops->init(dev, ringacc); + if (ret) + return ret; + + return 0; +} + U_BOOT_DRIVER(k3_navss_ringacc) = { .name = "k3-navss-ringacc", .id = UCLASS_MISC, |