diff options
author | Furquan Shaikh <furquan@google.com> | 2014-06-24 17:38:03 -0700 |
---|---|---|
committer | Marc Jones <marc.jones@se-eng.com> | 2015-03-04 18:15:44 +0100 |
commit | 84bbab9226163cca6ec58e4d5875fea1e53ec3b4 (patch) | |
tree | 50c751a94ea8ce33c17a00a02749181ef91a1b50 /src/soc/nvidia/tegra132/dma.c | |
parent | a89accd74ff6b9bdb8d27a0b7d5da9e7e5bd68c9 (diff) |
coreboot t132,rush: Add mainboard specific bootblock_init
Pull in mainboard specific bootblock_init function from nyan into
rush. Additionally, pull in all files required for proper compilation of rush
after adding the bootblock_init function
BUG=None
BRANCH=None
TEST=Compiles successfully for rush
Original-Change-Id: I69c736275f66eca3ad92f97d166e91d4c2301364
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/205583
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org>
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
(cherry picked from commit e7aac547026717d7380f71593010e3ea34ecea51)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: Ie26f91f8caaa06af3b195246febcdc70b9fe9795
Reviewed-on: http://review.coreboot.org/8570
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@google.com>
Diffstat (limited to 'src/soc/nvidia/tegra132/dma.c')
-rw-r--r-- | src/soc/nvidia/tegra132/dma.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/src/soc/nvidia/tegra132/dma.c b/src/soc/nvidia/tegra132/dma.c new file mode 100644 index 0000000000..3f236c3e22 --- /dev/null +++ b/src/soc/nvidia/tegra132/dma.c @@ -0,0 +1,149 @@ +/* + * (C) Copyright 2010,2011 + * NVIDIA Corporation <www.nvidia.com> + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <inttypes.h> +#include <stddef.h> +#include <stdlib.h> +#include <console/console.h> + +#include <arch/io.h> +#include <soc/addressmap.h> + +#include "dma.h" + +struct apb_dma * const apb_dma = (struct apb_dma *)TEGRA_APB_DMA_BASE; + +#define APB_DMA_OFFSET(n) \ + (struct apb_dma_channel_regs *)(TEGRA_APB_DMA_BASE + n) +struct apb_dma_channel apb_dma_channels[] = { + { .num = 0, .regs = APB_DMA_OFFSET(0x1000) }, + { .num = 1, .regs = APB_DMA_OFFSET(0x1040) }, + { .num = 2, .regs = APB_DMA_OFFSET(0x1080) }, + { .num = 3, .regs = APB_DMA_OFFSET(0x10c0) }, + { .num = 4, .regs = APB_DMA_OFFSET(0x1100) }, + { .num = 5, .regs = APB_DMA_OFFSET(0x1140) }, + { .num = 6, .regs = APB_DMA_OFFSET(0x1180) }, + { .num = 7, .regs = APB_DMA_OFFSET(0x11c0) }, + { .num = 8, .regs = APB_DMA_OFFSET(0x1200) }, + { .num = 9, .regs = APB_DMA_OFFSET(0x1240) }, + { .num = 10, .regs = APB_DMA_OFFSET(0x1280) }, + { .num = 11, .regs = APB_DMA_OFFSET(0x12c0) }, + { .num = 12, .regs = APB_DMA_OFFSET(0x1300) }, + { .num = 13, .regs = APB_DMA_OFFSET(0x1340) }, + { .num = 14, .regs = APB_DMA_OFFSET(0x1380) }, + { .num = 15, .regs = APB_DMA_OFFSET(0x13c0) }, + { .num = 16, .regs = APB_DMA_OFFSET(0x1400) }, + { .num = 17, .regs = APB_DMA_OFFSET(0x1440) }, + { .num = 18, .regs = APB_DMA_OFFSET(0x1480) }, + { .num = 19, .regs = APB_DMA_OFFSET(0x14c0) }, + { .num = 20, .regs = APB_DMA_OFFSET(0x1500) }, + { .num = 21, .regs = APB_DMA_OFFSET(0x1540) }, + { .num = 22, .regs = APB_DMA_OFFSET(0x1580) }, + { .num = 23, .regs = APB_DMA_OFFSET(0x15c0) }, + { .num = 24, .regs = APB_DMA_OFFSET(0x1600) }, + { .num = 25, .regs = APB_DMA_OFFSET(0x1640) }, + { .num = 26, .regs = APB_DMA_OFFSET(0x1680) }, + { .num = 27, .regs = APB_DMA_OFFSET(0x16c0) }, + { .num = 28, .regs = APB_DMA_OFFSET(0x1700) }, + { .num = 29, .regs = APB_DMA_OFFSET(0x1740) }, + { .num = 30, .regs = APB_DMA_OFFSET(0x1780) }, + { .num = 31, .regs = APB_DMA_OFFSET(0x17c0) }, +}; + +int dma_busy(struct apb_dma_channel * const channel) +{ + /* + * In continuous mode, the BSY_n bit in APB_DMA_STATUS and + * BSY in APBDMACHAN_CHANNEL_n_STA_0 will remain set as '1' so long + * as the channel is enabled. So for this function we'll use the + * DMA_ACTIVITY bit. + */ + return read32(&channel->regs->sta) & APB_STA_DMA_ACTIVITY ? 1 : 0; +} +/* claim a DMA channel */ +struct apb_dma_channel * const dma_claim(void) +{ + int i; + struct apb_dma_channel_regs *regs = NULL; + + /* + * Set global enable bit, otherwise register access to channel + * DMA registers will not be possible. + */ + setbits_le32(&apb_dma->command, APB_COMMAND_GEN); + + for (i = 0; i < ARRAY_SIZE(apb_dma_channels); i++) { + regs = apb_dma_channels[i].regs; + + if (!apb_dma_channels[i].in_use) { + u32 status = read32(®s->sta); + if (status & (1 << i)) { + /* FIXME: should this be fatal? */ + printk(BIOS_DEBUG, "%s: DMA channel %d busy?\n", + __func__, i); + } + break; + } + } + + if (i == ARRAY_SIZE(apb_dma_channels)) + return NULL; + + apb_dma_channels[i].in_use = 1; + return &apb_dma_channels[i]; +} + +/* release a DMA channel */ +void dma_release(struct apb_dma_channel * const channel) +{ + int i; + + /* FIXME: make this "thread" friendly */ + while (dma_busy(channel)) + ; + + channel->in_use = 0; + + /* clear the global enable bit if no channels are in use */ + for (i = 0; i < ARRAY_SIZE(apb_dma_channels); i++) { + if (apb_dma_channels[i].in_use) + return; + } + + clrbits_le32(&apb_dma->command, APB_COMMAND_GEN); +} + +int dma_start(struct apb_dma_channel * const channel) +{ + struct apb_dma_channel_regs *regs = channel->regs; + + /* Set ENB bit for this channel */ + setbits_le32(®s->csr, APB_CSR_ENB); + + return 0; +} + +int dma_stop(struct apb_dma_channel * const channel) +{ + struct apb_dma_channel_regs *regs = channel->regs; + + /* Clear ENB bit for this channel */ + clrbits_le32(®s->csr, APB_CSR_ENB); + + return 0; +} |