mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 23:51:33 +00:00
Merge branch 'master' of git://git.denx.de/u-boot-spi
This commit is contained in:
commit
b625fab706
12 changed files with 279 additions and 5 deletions
|
@ -23,3 +23,4 @@ CONFIG_DM_SPI_FLASH=y
|
|||
CONFIG_SPI_FLASH_BAR=y
|
||||
CONFIG_TIMER=y
|
||||
CONFIG_OMAP_TIMER=y
|
||||
CONFIG_DMA=y
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
menu "DMA Support"
|
||||
|
||||
config DMA
|
||||
bool "Enable Driver Model for DMA drivers"
|
||||
depends on DM
|
||||
help
|
||||
Enable driver model for DMA. DMA engines can do
|
||||
asynchronous data transfers without involving the host
|
||||
CPU. Currently, this framework can be used to offload
|
||||
memory copies to and from devices like qspi, ethernet
|
||||
etc Drivers provide methods to access the DMA devices
|
||||
buses that is used to transfer data to and from memory.
|
||||
The uclass interface is defined in include/dma.h.
|
||||
|
||||
config TI_EDMA3
|
||||
bool "TI EDMA3 driver"
|
||||
help
|
||||
Enable the TI EDMA3 driver for DRA7xx and AM43xx evms.
|
||||
This driver support data transfer between memory
|
||||
regions.
|
||||
|
||||
endmenu # menu "DMA Support"
|
|
@ -5,6 +5,8 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-$(CONFIG_DMA) += dma-uclass.o
|
||||
|
||||
obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
|
||||
obj-$(CONFIG_APBH_DMA) += apbh_dma.o
|
||||
obj-$(CONFIG_FSL_DMA) += fsl_dma.o
|
||||
|
|
72
drivers/dma/dma-uclass.c
Normal file
72
drivers/dma/dma-uclass.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Direct Memory Access U-Class driver
|
||||
*
|
||||
* (C) Copyright 2015
|
||||
* Texas Instruments Incorporated, <www.ti.com>
|
||||
*
|
||||
* Author: Mugunthan V N <mugunthanvnm@ti.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dma.h>
|
||||
#include <dm.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <errno.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int dma_get_device(u32 transfer_type, struct udevice **devp)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
for (ret = uclass_first_device(UCLASS_DMA, &dev); dev && !ret;
|
||||
ret = uclass_next_device(&dev)) {
|
||||
struct dma_dev_priv *uc_priv;
|
||||
|
||||
uc_priv = dev_get_uclass_priv(dev);
|
||||
if (uc_priv->supported & transfer_type)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dev) {
|
||||
error("No DMA device found that supports %x type\n",
|
||||
transfer_type);
|
||||
return -EPROTONOSUPPORT;
|
||||
}
|
||||
|
||||
*devp = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dma_memcpy(void *dst, void *src, size_t len)
|
||||
{
|
||||
struct udevice *dev;
|
||||
const struct dma_ops *ops;
|
||||
int ret;
|
||||
|
||||
ret = dma_get_device(DMA_SUPPORTS_MEM_TO_MEM, &dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ops = device_get_ops(dev);
|
||||
if (!ops->transfer)
|
||||
return -ENOSYS;
|
||||
|
||||
/* Invalidate the area, so no writeback into the RAM races with DMA */
|
||||
invalidate_dcache_range((unsigned long)dst, (unsigned long)dst +
|
||||
roundup(len, ARCH_DMA_MINALIGN));
|
||||
|
||||
return ops->transfer(dev, DMA_MEM_TO_MEM, dst, src, len);
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(dma) = {
|
||||
.id = UCLASS_DMA,
|
||||
.name = "dma",
|
||||
.flags = DM_UC_FLAG_SEQ_ALIAS,
|
||||
.per_device_auto_alloc_size = sizeof(struct dma_dev_priv),
|
||||
};
|
|
@ -11,6 +11,9 @@
|
|||
|
||||
#include <asm/io.h>
|
||||
#include <common.h>
|
||||
#include <dma.h>
|
||||
#include <dm/device.h>
|
||||
#include <asm/omap_common.h>
|
||||
#include <asm/ti-common/ti-edma3.h>
|
||||
|
||||
#define EDMA3_SL_BASE(slot) (0x4000 + ((slot) << 5))
|
||||
|
@ -31,6 +34,10 @@
|
|||
#define EDMA3_QEESR 0x108c
|
||||
#define EDMA3_QSECR 0x1094
|
||||
|
||||
struct ti_edma3_priv {
|
||||
u32 base;
|
||||
};
|
||||
|
||||
/**
|
||||
* qedma3_start - start qdma on a channel
|
||||
* @base: base address of edma
|
||||
|
@ -383,8 +390,8 @@ void qedma3_stop(u32 base, struct edma3_channel_config *cfg)
|
|||
__raw_writel(0, base + EDMA3_QCHMAP(cfg->chnum));
|
||||
}
|
||||
|
||||
void edma3_transfer(unsigned long edma3_base_addr, unsigned int
|
||||
edma_slot_num, void *dst, void *src, size_t len)
|
||||
void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num,
|
||||
void *dst, void *src, size_t len)
|
||||
{
|
||||
struct edma3_slot_config slot;
|
||||
struct edma3_channel_config edma_channel;
|
||||
|
@ -460,3 +467,74 @@ void edma3_transfer(unsigned long edma3_base_addr, unsigned int
|
|||
qedma3_stop(edma3_base_addr, &edma_channel);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DMA
|
||||
|
||||
void edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num,
|
||||
void *dst, void *src, size_t len)
|
||||
{
|
||||
__edma3_transfer(edma3_base_addr, edma_slot_num, dst, src, len);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int ti_edma3_transfer(struct udevice *dev, int direction, void *dst,
|
||||
void *src, size_t len)
|
||||
{
|
||||
struct ti_edma3_priv *priv = dev_get_priv(dev);
|
||||
|
||||
/* enable edma3 clocks */
|
||||
enable_edma3_clocks();
|
||||
|
||||
switch (direction) {
|
||||
case DMA_MEM_TO_MEM:
|
||||
__edma3_transfer(priv->base, 1, dst, src, len);
|
||||
break;
|
||||
default:
|
||||
error("Transfer type not implemented in DMA driver\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* disable edma3 clocks */
|
||||
disable_edma3_clocks();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ti_edma3_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct ti_edma3_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->base = dev_get_addr(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ti_edma3_probe(struct udevice *dev)
|
||||
{
|
||||
struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
|
||||
uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dma_ops ti_edma3_ops = {
|
||||
.transfer = ti_edma3_transfer,
|
||||
};
|
||||
|
||||
static const struct udevice_id ti_edma3_ids[] = {
|
||||
{ .compatible = "ti,edma3" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(ti_edma3) = {
|
||||
.name = "ti_edma3",
|
||||
.id = UCLASS_DMA,
|
||||
.of_match = ti_edma3_ids,
|
||||
.ops = &ti_edma3_ops,
|
||||
.ofdata_to_platdata = ti_edma3_ofdata_to_platdata,
|
||||
.probe = ti_edma3_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct ti_edma3_priv),
|
||||
};
|
||||
#endif /* CONFIG_DMA */
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
#include <linux/log2.h>
|
||||
#include <dma.h>
|
||||
|
||||
#include "sf_internal.h"
|
||||
|
||||
|
@ -454,8 +455,16 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: remove the weak after all the other spi_flash_copy_mmap
|
||||
* implementations removed from drivers
|
||||
*/
|
||||
void __weak spi_flash_copy_mmap(void *data, void *offset, size_t len)
|
||||
{
|
||||
#ifdef CONFIG_DMA
|
||||
if (!dma_memcpy(data, offset, len))
|
||||
return;
|
||||
#endif
|
||||
memcpy(data, offset, len);
|
||||
}
|
||||
|
||||
|
|
|
@ -336,7 +336,6 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
|
|||
struct omap3_spi_slave *ds = to_omap3_spi(slave);
|
||||
ulong start;
|
||||
int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
|
||||
int irqstatus = readl(&ds->regs->irqstatus);
|
||||
int i=0;
|
||||
|
||||
/*Enable SPI channel*/
|
||||
|
@ -351,7 +350,6 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
|
|||
/*Shift in and out 1 byte at time*/
|
||||
for (i=0; i < len; i++){
|
||||
/* Write: wait for TX empty (TXS == 1)*/
|
||||
irqstatus |= (1<< (4*(ds->slave.bus)));
|
||||
start = get_timer(0);
|
||||
while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
|
||||
OMAP3_MCSPI_CHSTAT_TXS)) {
|
||||
|
|
|
@ -158,6 +158,7 @@ static int spi_child_pre_probe(struct udevice *dev)
|
|||
slave->max_hz = plat->max_hz;
|
||||
slave->mode = plat->mode;
|
||||
slave->mode_rx = plat->mode_rx;
|
||||
slave->wordlen = SPI_DEFAULT_WORDLEN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -277,7 +277,7 @@ static int __ti_qspi_xfer(struct ti_qspi_priv *priv, unsigned int bitlen,
|
|||
}
|
||||
|
||||
/* TODO: control from sf layer to here through dm-spi */
|
||||
#ifdef CONFIG_TI_EDMA3
|
||||
#if defined(CONFIG_TI_EDMA3) && !defined(CONFIG_DMA)
|
||||
void spi_flash_copy_mmap(void *data, void *offset, size_t len)
|
||||
{
|
||||
unsigned int addr = (unsigned int) (data);
|
||||
|
|
|
@ -197,7 +197,11 @@
|
|||
/* Environment */
|
||||
#ifndef CONFIG_ENV_IS_NOWHERE
|
||||
# ifndef CONFIG_SYS_NO_FLASH
|
||||
/* Environment in NOR flash */
|
||||
# define CONFIG_ENV_IS_IN_FLASH
|
||||
# elif defined(CONFIG_ZYNQ_QSPI)
|
||||
/* Environment in Serial Flash */
|
||||
# define CONFIG_ENV_IS_IN_SPI_FLASH
|
||||
# elif defined(CONFIG_SYS_NO_FLASH)
|
||||
# define CONFIG_ENV_IS_NOWHERE
|
||||
# endif
|
||||
|
|
|
@ -31,6 +31,7 @@ enum uclass_id {
|
|||
UCLASS_CROS_EC, /* Chrome OS EC */
|
||||
UCLASS_DISK, /* Disk controller, e.g. SATA */
|
||||
UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */
|
||||
UCLASS_DMA, /* Direct Memory Access */
|
||||
UCLASS_RAM, /* RAM controller */
|
||||
UCLASS_ETH, /* Ethernet device */
|
||||
UCLASS_GPIO, /* Bank of general-purpose I/O pins */
|
||||
|
|
86
include/dma.h
Normal file
86
include/dma.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* (C) Copyright 2015
|
||||
* Texas Instruments Incorporated, <www.ti.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _DMA_H_
|
||||
#define _DMA_H_
|
||||
|
||||
/*
|
||||
* enum dma_direction - dma transfer direction indicator
|
||||
* @DMA_MEM_TO_MEM: Memcpy mode
|
||||
* @DMA_MEM_TO_DEV: From Memory to Device
|
||||
* @DMA_DEV_TO_MEM: From Device to Memory
|
||||
* @DMA_DEV_TO_DEV: From Device to Device
|
||||
*/
|
||||
enum dma_direction {
|
||||
DMA_MEM_TO_MEM,
|
||||
DMA_MEM_TO_DEV,
|
||||
DMA_DEV_TO_MEM,
|
||||
DMA_DEV_TO_DEV,
|
||||
};
|
||||
|
||||
#define DMA_SUPPORTS_MEM_TO_MEM BIT(0)
|
||||
#define DMA_SUPPORTS_MEM_TO_DEV BIT(1)
|
||||
#define DMA_SUPPORTS_DEV_TO_MEM BIT(2)
|
||||
#define DMA_SUPPORTS_DEV_TO_DEV BIT(3)
|
||||
|
||||
/*
|
||||
* struct dma_ops - Driver model DMA operations
|
||||
*
|
||||
* The uclass interface is implemented by all DMA devices which use
|
||||
* driver model.
|
||||
*/
|
||||
struct dma_ops {
|
||||
/*
|
||||
* Get the current timer count
|
||||
*
|
||||
* @dev: The DMA device
|
||||
* @direction: direction of data transfer should be one from
|
||||
enum dma_direction
|
||||
* @dst: Destination pointer
|
||||
* @src: Source pointer
|
||||
* @len: Length of the data to be copied.
|
||||
* @return: 0 if OK, -ve on error
|
||||
*/
|
||||
int (*transfer)(struct udevice *dev, int direction, void *dst,
|
||||
void *src, size_t len);
|
||||
};
|
||||
|
||||
/*
|
||||
* struct dma_dev_priv - information about a device used by the uclass
|
||||
*
|
||||
* @supported: mode of transfers that DMA can support, should be
|
||||
* one/multiple of DMA_SUPPORTS_*
|
||||
*/
|
||||
struct dma_dev_priv {
|
||||
u32 supported;
|
||||
};
|
||||
|
||||
/*
|
||||
* dma_get_device - get a DMA device which supports transfer
|
||||
* type of transfer_type
|
||||
*
|
||||
* @transfer_type - transfer type should be one/multiple of
|
||||
* DMA_SUPPORTS_*
|
||||
* @devp - udevice pointer to return the found device
|
||||
* @return - will return on success and devp will hold the
|
||||
* pointer to the device
|
||||
*/
|
||||
int dma_get_device(u32 transfer_type, struct udevice **devp);
|
||||
|
||||
/*
|
||||
* dma_memcpy - try to use DMA to do a mem copy which will be
|
||||
* much faster than CPU mem copy
|
||||
*
|
||||
* @dst - destination pointer
|
||||
* @src - souce pointer
|
||||
* @len - data length to be copied
|
||||
* @return - on successful transfer returns no of bytes
|
||||
transferred and on failure return error code.
|
||||
*/
|
||||
int dma_memcpy(void *dst, void *src, size_t len);
|
||||
|
||||
#endif /* _DMA_H_ */
|
Loading…
Reference in a new issue