first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
commit 1bf4efd552
2612 files changed
+636500

No files matched your search

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#ifndef __PRIMECELL_PL080DMAC_H
#define __PRIMECELL_PL080DMAC_H
#include <platform/soc/hwdmachannels.h>
#include <platform/soc/hwregbase.h>
#include <sys/task.h>
struct pl080dmac_channel_config {
uint8_t channel; /* dmac channel */
uint8_t type; /* source or destination */
uint32_t config; /* source or destination config register */
uint32_t control; /* source or destination control register */
uintptr_t fifo_address; /* source or destination address */
};
struct pl080dmac_config {
uint8_t dmac_clk;
uint32_t dmac_tc_irq;
uint32_t dmac_err_irq;
struct pl080dmac_channel_config dmac_channel_config[PL080DMAC_SUPPORTED_CHANNEL_COUNT];
};
#define PL080DMAC_PERPH_SRC (0)
#define PL080DMAC_PERPH_DEST (1)
#define PL080DMAC_FLOW_CTRL_DMAC (0)
#define PL080DMAC_FLOW_CTRL_SRC_PERPH (1)
#define PL080DMAC_FLOW_CTRL_DEST_PERPH (2)
#define PL080DMAC_XFER_WIDTH_BYTE (0)
#define PL080DMAC_XFER_WIDTH_HALF_WORD (1)
#define PL080DMAC_XFER_WIDTH_WORD (2)
#define PL080DMAC_MAX_TRANSFER_SIZE (0xFA0) /* Transfer size field in Channel_Config register is 12 bits wide (2^12 - 1). 0xFA0 is just a round up. */
#endif /* __PRIMECELL_PL080DMAC_H */
+329
View File
@@ -0,0 +1,329 @@
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <debug.h>
#include <drivers/dma.h>
#include <platform.h>
#include <platform/int.h>
#include <platform/pl080dmac_config.h>
#include <platform/soc/hwdmachannels.h>
#include <sys/task.h>
#include <sys/menu.h>
#include <sys.h>
#include "pl080dmac_regs.h"
#define CHANNEL_STATUS_UNINIT 0
#define CHANNEL_STATUS_IDLE 1
#define CHANNEL_STATUS_BUSY 2
#define CHANNEL_STATUS_BUSY_UNINIT 3
struct pl080dmac_channel {
uint8_t status;
uint32_t actual_xfer_size;
uint32_t current_xfer_size;
uint32_t total_xferred;
/* callback for async operations */
dma_completion_function callback;
void *callback_arg;
};
static bool pl080dmac_inited[PL080DMAC_COUNT];
static struct pl080dmac_channel pl080dmac_channels[PL080DMAC_COUNT][PL080DMAC_SUPPORTED_CHANNEL_COUNT];
static void pl080dmac_dump_channel(int dma_channel);
static void pl080dmac_tc_int_handler(void *arg);
static void pl080dmac_err_int_handler(void *arg);
void dma_init()
{
uint8_t pl080dmac_idx;
for (pl080dmac_idx = 0; pl080dmac_idx < PL080DMAC_COUNT; pl080dmac_idx++) {
clock_gate(pl080dmac_configs[pl080dmac_idx].dmac_clk, true);
if (pl080dmac_configs[pl080dmac_idx].dmac_tc_irq) {
set_int_type(pl080dmac_configs[pl080dmac_idx].dmac_tc_irq, INT_TYPE_IRQ | INT_TYPE_LEVEL);
install_int_handler(pl080dmac_configs[pl080dmac_idx].dmac_tc_irq, pl080dmac_tc_int_handler, (void *)pl080dmac_idx);
unmask_int(pl080dmac_configs[pl080dmac_idx].dmac_tc_irq);
}
if (pl080dmac_configs[pl080dmac_idx].dmac_err_irq) {
set_int_type(pl080dmac_configs[pl080dmac_idx].dmac_err_irq, INT_TYPE_IRQ | INT_TYPE_LEVEL);
install_int_handler(pl080dmac_configs[pl080dmac_idx].dmac_err_irq, pl080dmac_err_int_handler, (void *)pl080dmac_idx);
unmask_int(pl080dmac_configs[pl080dmac_idx].dmac_err_irq);
}
// Enable DMAC
rPL080DMAC_CFG(pl080dmac_idx) = (1 << 0);
pl080dmac_inited[pl080dmac_idx] = true;
}
}
int dma_execute_cmd(uint32_t cmd, int dma_channel, void *src,
void *dst, uint32_t length, uint32_t word_size,
uint32_t burst_size)
{
struct task_event event;
struct dma_segment seg;
void *fifo;
int32_t ret;
// build an SGL for the one segment
switch (cmd & DMA_CMD_DIR_MASK) {
case DMA_CMD_DIR_TX:
seg.paddr = (uintptr_t)src;
fifo = dst;
break;
case DMA_CMD_DIR_RX:
seg.paddr = (uintptr_t)dst;
fifo = src;
break;
default:
return -1;
}
seg.length = length;
// run the operation
event_init(&event, EVENT_FLAG_AUTO_UNSIGNAL, false);
ret = dma_execute_async(cmd, dma_channel, &seg, fifo, length, word_size, burst_size,
(dma_completion_function)event_signal, (void *)&event);
if (!ret)
// and block waiting for it to complete
event_wait(&event);
return ret;
}
int dma_execute_async(uint32_t cmd, int dma_channel,
struct dma_segment *sgl, void *fifo, uint32_t length,
uint32_t word_size, uint32_t burst_size,
dma_completion_function completion, void *completion_arg)
{
uint8_t dmac_idx;
struct pl080dmac_channel *ch;
const struct pl080dmac_channel_config *ch_config;
uint8_t expected_direction;
uint16_t xfer_size, xfer_width;
dmac_idx = (dma_channel >> DMA_SELECTOR_SHIFT) & DMA_CHANNEL_MASK;
dma_channel = dma_channel & DMA_CHANNEL_MASK;
ch = &pl080dmac_channels[dmac_idx][dma_channel];
ch_config = &pl080dmac_configs[dmac_idx].dmac_channel_config[dma_channel];
expected_direction = (ch_config->type == PL080DMAC_PERPH_SRC) ? DMA_CMD_DIR_RX : DMA_CMD_DIR_TX;
// sanity check
ASSERT(dmac_idx <= PL080DMAC_COUNT);
ASSERT(dma_channel <= PL080DMAC_CHANNEL_COUNT);
ASSERT(sgl);
ASSERT(length > 0);
ASSERT((uintptr_t)fifo == ch_config->fifo_address);
// make sure controller is inited
ASSERT(pl080dmac_inited[dmac_idx] != false);
// word_size and burst_size default are in pl080dmac_config table, overrides not allowed
ASSERT(word_size == 0);
ASSERT(burst_size == 0);
// validate command
ASSERT((cmd & DMA_CMD_DIR_MASK) == expected_direction);
// update channel status to busy but not initialized
enter_critical_section();
ch->status = CHANNEL_STATUS_BUSY_UNINIT;
exit_critical_section();
// save the completion
ch->callback = completion;
ch->callback_arg = completion_arg;
// calcuate transfer size, and cap it to max_trasnfer_size
xfer_width = (expected_direction == DMA_CMD_DIR_RX) ?
(ch_config->control >> 21) & 7 : (ch_config->control >> 18) & 7;
// make sure length is multiple of transfer width
ASSERT((length % (1 << xfer_width)) == 0);
xfer_size = length >> xfer_width;
ch->actual_xfer_size = xfer_size;
xfer_size = (xfer_size < PL080DMAC_MAX_TRANSFER_SIZE) ? xfer_size : PL080DMAC_MAX_TRANSFER_SIZE;
ch->current_xfer_size = xfer_size;
ch->total_xferred = 0;
// initialize and configure channel
// PL080DMAC TRM, section 3.2.7
// step 2
rPL080DMAC_INTTCCLR(dmac_idx) = (1 << dma_channel);
rPL080DMAC_INTERRCLR(dmac_idx) = (1 << dma_channel);
// step 3,4,6,7
if (ch_config->type == PL080DMAC_PERPH_SRC) {
rPL080DMAC_CHCTRL(dmac_idx, dma_channel) = (1 << 31) | (ch_config->control) | xfer_size;
rPL080DMAC_CHCFG(dmac_idx, dma_channel) = (1 << 15) | (1 << 14) | (ch_config->config);
rPL080DMAC_CHSRCADDR(dmac_idx, dma_channel) = ch_config->fifo_address;
rPL080DMAC_CHDESTADDR(dmac_idx, dma_channel) = sgl->paddr;
} else {
rPL080DMAC_CHCTRL(dmac_idx, dma_channel) = (1 << 31) | (ch_config->control) | xfer_size;
rPL080DMAC_CHCFG(dmac_idx, dma_channel) = (1 << 15) | (1 << 14) | (ch_config->config);
rPL080DMAC_CHDESTADDR(dmac_idx, dma_channel) = ch_config->fifo_address;
rPL080DMAC_CHSRCADDR(dmac_idx, dma_channel) = sgl->paddr;
}
// we only support 1 segment (linear dma)
rPL080DMAC_CHLLI(dmac_idx, dma_channel) = 0;
// update channel status to busy
enter_critical_section();
ch->status = CHANNEL_STATUS_BUSY;
exit_critical_section();
// start channel
rPL080DMAC_CHCFG(dmac_idx, dma_channel) |= (1 << 0);
return 0;
}
void dma_cancel(int dma_channel)
{
uint8_t dmac_idx;
struct pl080dmac_channel *ch;
utime_t start_time;
dmac_idx = (dma_channel >> DMA_SELECTOR_SHIFT) & DMA_CHANNEL_MASK;
dma_channel = dma_channel & DMA_CHANNEL_MASK;
ch = &pl080dmac_channels[dmac_idx][dma_channel];
// make sure controller is inited
ASSERT(pl080dmac_inited[dmac_idx] != false);
// sanity check
ASSERT(dmac_idx <= PL080DMAC_COUNT);
ASSERT(dma_channel <= PL080DMAC_CHANNEL_COUNT);
// it's legal but not interesting to cancel a channel that hasn't been initialized
if (CHANNEL_STATUS_UNINIT == ch->status)
return;
start_time = system_time();
rPL080DMAC_CHCFG(dmac_idx, dma_channel) = 0;
while ((rPL080DMAC_ENBLDCHNLS(dmac_idx) >> dma_channel) != 0) {
if (time_has_elapsed(start_time, 10000))
panic("PL080DMAC%d: channel %d timeout during abort", dmac_idx, dma_channel);
}
// mark the channel idle
ch->status = CHANNEL_STATUS_IDLE;
}
void dma_use_int(int dma_channel, bool use)
{
uint8_t dmac_idx;
dmac_idx = (dma_channel >> DMA_SELECTOR_SHIFT) & DMA_CHANNEL_MASK;
dma_channel = dma_channel & DMA_CHANNEL_MASK;
if (use)
rPL080DMAC_CHCFG(dmac_idx, dma_channel) |= ((1 << 14) | (1 << 15));
else
rPL080DMAC_CHCFG(dmac_idx, dma_channel) &= ~((1 << 14) | (1 << 15));
}
bool dma_poll(int dma_channel)
{
bool ret = false;
struct pl080dmac_channel *ch;
uint8_t dmac_idx;
dmac_idx = (dma_channel >> DMA_SELECTOR_SHIFT) & DMA_CHANNEL_MASK;
dma_channel = dma_channel & DMA_CHANNEL_MASK;
ch = &pl080dmac_channels[dmac_idx][dma_channel];
if (CHANNEL_STATUS_IDLE == ch->status) {
ret = true;
goto exit;
}
enter_critical_section();
if (rPL080DMAC_INTTCSTATUS(dmac_idx) >> dma_channel)
pl080dmac_tc_int_handler((void *)dmac_idx);
else if (rPL080DMAC_INTERRSTATUS(dmac_idx) >> dma_channel)
pl080dmac_err_int_handler((void *)dmac_idx);
exit_critical_section();
if (CHANNEL_STATUS_IDLE == ch->status) {
ret = true;
goto exit;
}
exit:
return ret;
}
int dma_set_aes(int dma_channel, struct dma_aes_config *config)
{
// Not supported (PL080DMAC doesn't support AES)
return -1;
}
static void pl080dmac_tc_int_handler(void *args)
{
uint8_t pl080dmac_idx;
uint32_t tc_intsts;
uint8_t ch;
struct pl080dmac_channel *ch_info;
pl080dmac_idx = (uint8_t)args;
RELEASE_ASSERT(pl080dmac_idx < PL080DMAC_COUNT);
tc_intsts = rPL080DMAC_INTTCSTATUS(pl080dmac_idx);
rPL080DMAC_INTTCCLR(pl080dmac_idx) = tc_intsts;
while(tc_intsts != 0) {
ch = 31 - clz(tc_intsts);
ch_info = &pl080dmac_channels[pl080dmac_idx][ch];
ch_info->total_xferred += ch_info->current_xfer_size;
if (ch_info->total_xferred < ch_info->actual_xfer_size) {
// start again
}
else {
ch_info->status = CHANNEL_STATUS_IDLE;
// call the user-supplied callback
if (ch_info->callback != NULL)
ch_info->callback(ch_info->callback_arg);
}
tc_intsts &= ~(1 << ch);
}
}
static void pl080dmac_err_int_handler(void *args)
{
uint8_t pl080dmac_idx;
uint32_t err_intsts;
pl080dmac_idx = (uint8_t)args;
RELEASE_ASSERT(pl080dmac_idx < PL080DMAC_COUNT);
err_intsts = rPL080DMAC_INTERRSTATUS(pl080dmac_idx);
rPL080DMAC_INTERRCLR(pl080dmac_idx) = err_intsts;
panic("PL080DMAC reported error on channels:0x%08x\n", err_intsts);
}
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#ifndef _PL080DMAC_REGS_H
#define _PL080DMAC_REGS_H
#include <platform/soc/hwregbase.h>
#define rPL080DMAC_INTSTATUS(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0000)
#define rPL080DMAC_INTTCSTATUS(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0004)
#define rPL080DMAC_INTTCCLR(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0008)
#define rPL080DMAC_INTERRSTATUS(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x000C)
#define rPL080DMAC_INTERRCLR(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0010)
#define rPL080DMAC_RAWINTTCSTATUS(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0014)
#define rPL080DMAC_RAWINTERRSTATUS(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0018)
#define rPL080DMAC_ENBLDCHNLS(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x001C)
#define rPL080DMAC_SOFTBREQ(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0020)
#define rPL080DMAC_SOFTSREQ(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0024)
#define rPL080DMAC_SOFTLBREQ(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0028)
#define rPL080DMAC_SOFTLSREQ(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x002C)
#define rPL080DMAC_CFG(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0030)
#define rPL080DMAC_SYNC(_n) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0034)
#define rPL080DMAC_CHSRCADDR(_n, _c) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0100 + ((_c) * 0x20))
#define rPL080DMAC_CHDESTADDR(_n, _c) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0104 + ((_c) * 0x20))
#define rPL080DMAC_CHLLI(_n, _c) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0108 + ((_c) * 0x20))
#define rPL080DMAC_CHCTRL(_n, _c) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x010C + ((_c) * 0x20))
#define rPL080DMAC_CHCFG(_n, _c) *(volatile uint32_t *)(PL080DMAC_BASE_ADDR + ((_n) * PL080DMAC_SPACING) + 0x0110 + ((_c) * 0x20))
#endif /* _PL080DMAC_REGS_H */
+18
View File
@@ -0,0 +1,18 @@
# Copyright (C) 2013 Apple Inc. All rights reserved.
#
# This document is the property of Apple Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Inc.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
GLOBAL_INCLUDES += $(LOCAL_DIR)/include
OPTIONS += \
WITH_HW_DMA=1
ALL_OBJS += \
$(LOCAL_DIR)/pl080dmac.o
+300
View File
@@ -0,0 +1,300 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <arch.h>
#include <debug.h>
#include <lib/libc.h>
#include <platform.h>
#include <platform/int.h>
#include <sys.h>
#include <arch/arm/arm.h>
#if WITH_HW_EDGEIC
#include <drivers/edgeic.h>
#endif
#include "pl192vic.h"
#define MAX_INTS (VICS_COUNT * 32)
static struct interrupt_entry handlers[MAX_INTS];
extern void __arm_irq(void);
#if SUPPORT_SLEEP
struct vic_state {
u_int32_t enabled;
u_int32_t select;
};
static struct vic_state vic_saved_state[VICS_COUNT];
# define SAVE_ENABLED(_v, _i, _s) \
do { \
if (_s) { \
vic_saved_state[(_v)].enabled |= (1 << (_i)); \
} else { \
vic_saved_state[(_v)].enabled &= ~(1<< (_i)); \
} \
} while(0)
# define SAVE_SELECT(_v, _i, _s) \
do { \
if (_s) { \
vic_saved_state[(_v)].select |= (1 << (_i)); \
} else { \
vic_saved_state[(_v)].select &= ~(1<< (_i)); \
} \
} while(0)
#else
# define SAVE_ENABLED(_v, _i, _s)
# define SAVE_SELECT(_v, _i, _s)
#endif /* SUPPORT_SLEEP */
int interrupt_init(void)
{
u_int32_t vic, vec;
#if WITH_HW_EDGEIC
/* clear the pending int source block */
edgeic_reset();
#endif
for (vic = 0; vic < VICS_COUNT; vic++) {
/* mask everything */
rVICINTENCLEAR(vic) = 0xffffffff;
/* set all vectors as int */
rVICINTSELECT(vic) = 0;
/* unmask all priority levels */
rVICSWPRIORITYMASK(vic) = 0xffff;
/* set up all the vector addresses with the vector number */
for(vec = 0; vec < 32; vec++) {
rVICVECTADDR(vic, vec) = vic * 32 + vec;
}
#if SUPPORT_SLEEP
/* restore saved state, or initialize to all off */
rVICINTENABLE(vic) = vic_saved_state[vic].enabled;
rVICINTSELECT(vic) = vic_saved_state[vic].select;
/* if any vectors are FIQs, unmask FIQ */
if (vic_saved_state[vic].select != 0)
arm_enable_fiqs();
#endif
}
/* also enable it */
exit_critical_section();
return 0;
}
void interrupt_mask_all(void)
{
u_int32_t vic;
/* mask everything */
for (vic = 0; vic < VICS_COUNT; vic++) {
rVICINTENCLEAR(vic) = 0xffffffff;
}
}
void mask_int(u_int32_t vector)
{
u_int32_t vic = vector / 32;
u_int32_t vec = vector % 32;
ASSERT(vic < VICS_COUNT);
enter_critical_section();
rVICINTENCLEAR(vic) |= 1 << vec;
SAVE_ENABLED(vic, vec, false);
exit_critical_section();
}
void unmask_int(u_int32_t vector)
{
u_int32_t vic = vector / 32;
u_int32_t vec = vector % 32;
ASSERT(vic < VICS_COUNT);
enter_critical_section();
rVICINTENABLE(vic) |= 1 << vec;
SAVE_ENABLED(vic, vec, true);
exit_critical_section();
}
void set_int_type(uint32_t vector, int type)
{
u_int32_t vic = vector / 32;
u_int32_t vec = vector % 32;
bool edge;
ASSERT(vic < VICS_COUNT);
enter_critical_section();
if (type & INT_TYPE_FIQ) {
rVICINTSELECT(vic) |= (1 << vec);
SAVE_SELECT(vic, vec, true);
arm_enable_fiqs();
} else {
rVICINTSELECT(vic) &= ~(1 << vec);
SAVE_SELECT(vic, vec, false);
}
edge = (type & INT_TYPE_EDGE) != 0;
#if WITH_HW_EDGEIC
handlers[vector].edge = edge;
edgeic_select_edge(vector, edge);
#else
if (edge)
panic("set_int_type: edge not supported\n");
#endif
exit_critical_section();
}
int install_int_handler(uint32_t vector, int_handler handler, void *arg)
{
ASSERT(vector < MAX_INTS);
enter_critical_section();
handlers[vector].handler = handler;
handlers[vector].arg = arg;
exit_critical_section();
return 0;
}
void platform_irq(void)
{
u_int32_t vic, vector;
for (vic = 0; vic < VICS_COUNT; vic++) {
if (rVICIRQSTATUS(vic) != 0) {
break;
}
}
if (vic >= VICS_COUNT) {
return; // false alarm
}
vector = rVICADDR(vic);
// printf("irq: %d\n", vector);
if (vector < MAX_INTS ) {
if (handlers[vector].edge) {
#if WITH_HW_EDGEIC
edgeic_clear_interrupt(vector);
#else
panic("platform_irq: edge not supported\n");
#endif
}
if (handlers[vector].handler)
handlers[vector].handler(handlers[vector].arg);
} else {
void (*crap_isr)(void);
crap_isr = (void (*)(void) )vector;
crap_isr();
}
/* EOI the interrupt controller */
rVICADDR(vic) = 1;
}
void platform_fiq(void)
{
u_int32_t vic, pending = 0, vector = 0;
for (vic = 0; vic < VICS_COUNT; vic++) {
pending = rVICFIQSTATUS(vic);
if (pending != 0) break;
vector += 32;
}
if (pending == 0) {
return;
}
vector += __builtin_ctz(pending);
// printf("fiq: 0x%x %d\n", pending, vector);
if (handlers[vector].handler)
handlers[vector].handler(handlers[vector].arg);
}
#ifdef IPC_VIC_BASE_ADDR
/*
* Ring our partner's doorbell.
*/
void interrupt_generate_ipc(u_int32_t vector)
{
u_int32_t vic = vector / 32;
u_int32_t vec = vector % 32;
rVICIPCSOFTINT(vic) = (1 << vec);
}
/*
* Clear the doorbell interrupt from our partner.
*/
void interrupt_clear_ipc(u_int32_t vector)
{
u_int32_t vic = vector / 32;
u_int32_t vec = vector % 32;
rVICSOFTINTCLEAR(vic) = (1 << vec);
}
#endif
static void
do_int_panic(void *arg __unused)
{
int vic, vec;
for (vic = 0; vic < VICS_COUNT; vic++) {
u_int32_t en = rVICINTENABLE(vic);
u_int32_t stat = rVICIRQSTATUS(vic);
printf("rVICINTENABLE(%d) = 0x%08x\n", vic, en);
printf("rVICIRQSTATUS(%d) = 0x%08x\n", vic, stat);
for (vec = 0; vec < 32; vec++) {
const int vector = (vic * 32) + vec;
const struct interrupt_entry *entry = &handlers[vector];
const bool enabled = en & (1 << vec);
const bool requested = stat & (1 << vec);
// Print if it's enabled, requested or has a handler
if (enabled || requested || (NULL != entry->handler)) {
printf("vector[%d]: %s:%d - h=%p\n", vector,
(enabled ? "unmsk" : "mask"),
(requested ? 1 : 0),
entry->handler);
}
}
}
}
#if APPLICATION_EMBEDDEDIOP
PANIC_HOOK(irq, do_int_panic, NULL);
#endif
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#ifndef __PRIMECELL_PL192VIC_H
#define __PRIMECELL_PL192VIC_H
#include <platform/soc/hwregbase.h>
#define rVICIRQSTATUS(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x000))
#define rVICFIQSTATUS(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x004))
#define rVICRAWINTR(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x008))
#define rVICINTSELECT(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x00C))
#define rVICINTENABLE(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x010))
#define rVICINTENCLEAR(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x014))
#define rVICSOFTINT(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x018))
#define rVICSOFTINTCLEAR(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x01C))
#define rVICPROTECTION(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x020))
#define rVICSWPRIORITYMASK(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x024))
#define rVICPRIORITYDAISY(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x028))
#define rVICVECTADDR(v, n) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x100 + (n) * 4))
#define rVICVECTPRIO(n) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x200 + (n) * 4))
#define rVICADDR(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0xF00))
#define rVICPERID0(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0xFE0))
#define rVICPERID1(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0xFE4))
#define rVICPERID2(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0xFE8))
#define rVICPERID3(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0xFEC))
#define rVICPCELLID0(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0xFF0))
#define rVICPCELLID1(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0xFF4))
#define rVICPCELLID2(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0xFF8))
#define rVICPCELLID3(v) (*(volatile u_int32_t *)(VIC_BASE_ADDR + (v) * VIC_STRIDE + 0xFFC))
/*
* If the platform has a VIC used for inter-processor communication,
* we need to be able to touch its soft-int register.
*/
#ifdef IPC_VIC_BASE_ADDR
# define rVICIPCSOFTINT(v) (*(volatile u_int32_t *)(IPC_VIC_BASE_ADDR + (v) * VIC_STRIDE + 0x018))
#endif
#endif /* __PRIMECELL_PL192VIC_H */
+15
View File
@@ -0,0 +1,15 @@
# Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
#
# This document is the property of Apple Computer, Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Computer, Inc.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
OPTIONS += \
WITH_HW_VIC=1
ALL_OBJS += $(LOCAL_DIR)/pl192vic.o