T113-i 通用工控主板
L13819506056 发布的帖子
-
回复: T113-S3 G2D 裸机测试
__s32 drv_g2d_init(void) { memset(&g2d_ext_hd, 0, sizeof(__g2d_drv_t)); init_wait_event(&g2d_ext_hd.wait_event); g2d_top_set_base((unsigned long) para.io); #if defined(CONFIG_SUNXI_G2D_ROTATE) g2d_rot_set_base((unsigned long) para.io); #endif return 0; } int g2d_probe(void ) { __g2d_info_t *info = NULL; info = ¶ info->dev = 0; info->io = (__u32 *)0x05410000; info->irq = 121; info->clk = (__u32 *)0x02001630; info->clk_parent = 0; info->bus_clk = (__u32 *)0x0200163c; info->mbus_clk = (__u32 *)0x02001804; bsp_int_vect_set(info->irq, /* Assign ISR handler. */ 8u, /* 中断的优先级 */ 1u, /* 中断的目标CPU */ 0u, /* 参数 */ g2d_handle_irq); irq_enable(info->irq);// drv_g2d_init(); mutex_init(&info->mutex); mutex_init(&global_lock); return 0; }
-
T113-S3 的SMHC1连接SD-NAND问题:
T113-s3的SMHC1接一片SD NAND ,但在读取数据时,传输描述符配置都正确的情况下。iDMA始终报描述符不可用中断。status_t sd_mmc_set_dma_table_config(v3x_sd_mmc_t *base,
sd_mmc_dma_config_t *dma_config,
sd_mmc_data_t *data_config,
uint32_t flags)
{
base->DMAC = 1;//IMAC 复位
const uint32_t *start_address;
uint32_t entries;
uint32_t i, dma_buffer_len = 0U;
sd_mmc_dma_descriptor_t *dma_entry_address;uint32_t data_bytes = data_config->block_size * data_config->block_count; const uint32_t *data = (data_config->rx_data == NULL) ? data_config->tx_data : data_config->rx_data; /* check DMA data buffer address align or not */ if ( ((uint32_t)data & 0x03) != 0U ) { return STA_DMA_DATA_ADDR_NOT_ALIGN; } /* * Add non aligned access support ,user need make sure your buffer size is big * enough to hold the data,in other words,user need make sure the buffer size * is 4 byte aligned */ data_bytes = (data_bytes + 3) & (~3); start_address = data; base->GCTL |= (SDXC_FIFO_RESET | SDXC_DMA_RESET | SDXC_DMA_ENABLE_BIT);/* reset fifo & dma*/ /* Check if ADMA descriptor's number is enough. */ if ((data_bytes % MMC_SD_DMA_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) == 0U) entries = data_bytes / MMC_SD_DMA_DESCRIPTOR_MAX_LENGTH_PER_ENTRY; else entries = ((data_bytes / MMC_SD_DMA_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U); if (entries > ((dma_config->dma_table_words * sizeof(uint32_t)) / sizeof(sd_mmc_dma_descriptor_t))) { /*如果超过预置(1个)数量,应该支持动态分配描述符表 */ if( STA_SUCCESS != sd_mmc_malloc_dma_descriptor( dma_config,entries)) return STA_MEM_ERROR; } dma_entry_address = (sd_mmc_dma_descriptor_t *)(dma_config->dma_table); for (i = 0U; i < entries; i++) { if (data_bytes > MMC_SD_DMA_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) { dma_buffer_len = MMC_SD_DMA_DESCRIPTOR_MAX_LENGTH_PER_ENTRY; data_bytes -= dma_buffer_len; } else { dma_buffer_len = data_bytes; } /* */ dma_entry_address[i].buf_addr_ptr = (uint32_t)start_address; dma_entry_address[i].buf_size = dma_buffer_len ; dma_entry_address[i].config = SD_MMC_DESCRIPTOR_TC_INT_DIS | SD_MMC_DESCRIPTOR_CHAIM_MOD | SD_MMC_DESCRIPTOR_OWN_FLAG; dma_entry_address[i].buf_addr_next = (uint32_t)&dma_entry_address[i + 1]; start_address += (dma_buffer_len / sizeof(uint32_t));/*32bit 偏移*/ } /* set the end bit */ dma_entry_address[0].config = SD_MMC_DESCRIPTOR_FIRST_FLAG | SD_MMC_DESCRIPTOR_TC_INT_DIS | SD_MMC_DESCRIPTOR_CHAIM_MOD | SD_MMC_DESCRIPTOR_OWN_FLAG; uint32_t config = dma_entry_address[i - 1U].config & (~(SD_MMC_DESCRIPTOR_TC_INT_DIS )); dma_entry_address[i - 1U].config = config | SD_MMC_DESCRIPTOR_LAST_FLAG;// \ // | (1 << 5); /* end of ring */ dma_entry_address[i - 1U].buf_addr_next = 0; base->DMAC = (1 << 1) | (1 << 7); /* enable dma interrupt */ base->IDST = 0x3F; /*清除DMA中断状态 */ /*config the burst length */ base->FWLR = (burst_len_16 << 28) | (0x0f << 16) | 240;//0x10; /*允许dma中断 */ if(data_config->rx_data) { /*DMA 接收利用 DMA传输完毕产生中断*/ base->IDIE = ( SDXC_IDMAC_RECEIVE_INTERRUPT | SDXC_IDMAC_FATAL_BUS_ERROR | SDXC_IDMAC_DESTINATION_INVALID | SDXC_IDMAC_CARD_ERROR_SUM); base->IMKR &= ~(1 << 3); } else if(data_config->tx_data) { /*DMA 传输利用 MCI传输完毕产生中断*/ base->IDIE = ( SDXC_IDMAC_FATAL_BUS_ERROR | SDXC_IDMAC_TRANSMIT_INTERRUPT | SDXC_IDMAC_DESTINATION_INVALID | SDXC_IDMAC_CARD_ERROR_SUM); base->IMKR |= (1 << 3); } else base->IDIE = 0; base->DLBA = (uint32_t)(dma_config->dma_table); /* enable DMA */ sd_mmc_enable_dma(base);
/*动态分配的内存 ,需要刷新cache */
if (entries > ((dma_config->dma_table_words * sizeof(uint32_t)) / sizeof(sd_mmc_dma_descriptor_t)))
{
L1C_CleanDataCacheRange(dma_config->dma_table,dma_config->dma_table_words * entries);
}return STA_SUCCESS;
}
上面说使用的描述符的内存空间是位于非cache段的内存中。
从内存数据看配置都是正确的,数据已经从sd nsnd 传输到fifo中了,而 IDMA总是报描述符不可用,致使数据不能从fifo读取到内存中。 大家帮我看看问题可能在哪里。 -
T113-S3 G2D 裸机测试
终于将G2D裸机环境使用搞定了。 简单测试了一下bitblt 和矩形填充。
extern const unsigned char image_mn_map[800*480*4];/*图片文件*/ void g2d_test(void) { g2d_probe(); g2d_open(); g2d_blt_h blit_para; while(1) { /* bitblt测试 */ memset(&blit_para,0,sizeof(g2d_blt_h)); g2d_image_enh *src = &blit_para.src_image_h; g2d_image_enh *des = &blit_para.dst_image_h; blit_para.flag_h = G2D_ROT_180;//G2D_ROT_V;// G2D_ROT_0; src->laddr[0] = (uint32_t)image_mn_map; src->align[0] = 4; src->clip_rect.w = 800; src->clip_rect.h = 480; src->width = 800; src->height = 480; src->format = G2D_FORMAT_ARGB8888; src->mode = G2D_PIXEL_ALPHA; src->bpremul = 0; des->laddr[0] = r528_de_config.LayerAddr[0] ; des->align[0] = 4; des->clip_rect.w = 800; des->clip_rect.h = 480; des->width = 800; des->height = 480; des->format = G2D_FORMAT_ARGB8888; des->mode = G2D_PIXEL_ALPHA; des->bpremul = 0; long ret = g2d_ioctl( G2D_CMD_BITBLT_H, (unsigned long )&blit_para); /* 矩形填充测试 */ g2d_fillrect_h fill_para; memset(&fill_para,0,sizeof(g2d_fillrect_h)); src = &fill_para.dst_image_h; src->laddr[0] = (uint32_t)r528_de_config.LayerAddr[0] ;; src->align[0] = 4; src->clip_rect.w = 800; src->clip_rect.h = 480; src->width = 800; src->height = 480; src->format = G2D_FORMAT_ARGB8888; src->mode = G2D_PIXEL_ALPHA; src->bpremul = 0; src->gamut = G2D_BT709; src->color = 0xFFFF0000; src->alpha = 0xff; ret = g2d_ioctl( G2D_CMD_FILLRECT_H, (unsigned long )&fill_para); } }
-
T113-S3 CAN模块使用的全部信息
经过实际测试,T133-S3的CAN模块完全可用。测试相关信息如下:
#define CAN0 0x02504000 #define CAN1 0x02504400 #define CAN_OFFSET(can_base,offset) (*((volatile uint32_t *)(can_base + (offset)))) #define CAN_MSEL(can_base) CAN_OFFSET(can_base,0x0000) //CAN mode select register #define CAN_CMD(can_base) CAN_OFFSET(can_base,0x0004) //CAN command register #define CAN_STA(can_base) CAN_OFFSET(can_base,0x0008) //CAN status register #define CAN_INT(can_base) CAN_OFFSET(can_base,0x000C) //CAN interrupt register #define CAN_INTEN(can_base) CAN_OFFSET(can_base,0x0010) //CAN interrupt enable register #define CAN_BUSTIME(can_base) CAN_OFFSET(can_base,0x0014) //CAN bus timing register #define CAN_TEWL(can_base) CAN_OFFSET(can_base,0x0018) //CAN TX error warning limit register #define CAN_ERRC(can_base) CAN_OFFSET(can_base,0x001c) //CAN error counter register #define CAN_RMCNT(can_base) CAN_OFFSET(can_base,0x0020) //CAN receive message counter register #define CAN_RBUF_SADDR(can_base) CAN_OFFSET(can_base,0x0024) //CAN receive buffer start address register #define CAN_TRBUF0(can_base) CAN_OFFSET(can_base,0x0040) //CAN TX/RX message buffer 0 register #define CAN_TRBUF1(can_base) CAN_OFFSET(can_base,0x0044) //CAN TX/RX message buffer 0 register #define CAN_TRBUF2(can_base) CAN_OFFSET(can_base,0x0048) //CAN TX/RX message buffer 0 register #define CAN_TRBUF3(can_base) CAN_OFFSET(can_base,0x004c) //CAN TX/RX message buffer 0 register #define CAN_TRBUF4(can_base) CAN_OFFSET(can_base,0x0050) //CAN TX/RX message buffer 0 register #define CAN_TRBUF5(can_base) CAN_OFFSET(can_base,0x0054) //CAN TX/RX message buffer 0 register #define CAN_TRBUF6(can_base) CAN_OFFSET(can_base,0x0058) //CAN TX/RX message buffer 0 register #define CAN_TRBUF7(can_base) CAN_OFFSET(can_base,0x005c) //CAN TX/RX message buffer 0 register #define CAN_TRBUF8(can_base) CAN_OFFSET(can_base,0x0060) //CAN TX/RX message buffer 0 register #define CAN_TRBUF9(can_base) CAN_OFFSET(can_base,0x0064) //CAN TX/RX message buffer 0 register #define CAN_TRBUF10(can_base) CAN_OFFSET(can_base,0x0068) //CAN TX/RX message buffer 0 register #define CAN_TRBUF11(can_base) CAN_OFFSET(can_base,0x006c) //CAN TX/RX message buffer 0 register #define CAN_TRBUF12(can_base) CAN_OFFSET(can_base,0x0070) //CAN TX/RX message buffer 0 register #define CAN_ACPC(can_base) CAN_OFFSET(can_base,0x0028) //CAN acceptance code 0 register(reset mode) #define CAN_ACPM(can_base) CAN_OFFSET(can_base,0x002C) //CAN acceptance mask 0 register(reset mode) #define CAN_RBUF_RBACK(can_base) CAN_OFFSET(can_base,0x0180) //~0x1b0 //CAN transmit buffer for read back register #define CAN_VERSION(can_base) CAN_OFFSET(can_base,0x0300) //CAN Version Register typedef struct _t113_can_control_t_ { volatile uint32_t * can_clk_gate; uint32_t can_base; uint32_t int_id; }t113_can_control_t; t113_can_control_t t113_can[2] = { { (volatile uint32_t *)0x0200192C, 0x02504000, 53 }, { (volatile uint32_t *)0x0200192C, 0x02504400, 54 } }; uint32_t rxd_buf[13]; void t113_can_irq_handle(void* p) { uint32_t can_base = (uint32_t) p; uint32_t int_sta = CAN_INT(can_base); if(int_sta & 1) { /* 接收中断 */ can_read_data(can_base,rxd_buf); /* 后续处理 */ } if(int_sta & 2 ) { /*发送中断*/ } if(int_sta & 0xFC ) { /* 错 误 中断 */ } CAN_INT(can_base) = int_sta; } void ini_can(int can_id) { if(can_id > 1) return; GPIOB->CFG0 &= ~(0xff00 << (can_id * 8)); GPIOB->CFG0 |= (0x8800 << (can_id * 8)); GPIOB->DRV0 |= (0x3300 << (can_id * 8)); t113_can_control_t * can_info = &t113_can[can_id]; uint32_t can_base = can_info->can_base; int can_int_id = can_info->int_id; *can_info->can_clk_gate |= (1 << (16 + can_id)) | (1 << can_id);/* CCU_CAN_BGR */ CAN_MSEL(can_base) |= 1; /* Reset mode selected*/ /* 500KHz CAN速率 */ CAN_BUSTIME(can_base) = (9 /* apb_clk = 100Mz , 100/10 = 10MHz*/ | (1 << 14) /* Synchronization Jump Width :2 Tq clock cycles */ | (13 << 16) /*Phase Segment 1 : 14 Tq clock cycles */ | ( 3 << 20) /*Phase Segment 2 : 4 Tq clock cycles */ | ( 0 << 23)); /* Bus line is sampled three times at the sample point */ CAN_ACPC(can_base) = 0xffffffff; /*实际使用时根据需要设置滤波*/ CAN_ACPM(can_base) = 0xffffffff; /*实际使用时根据需要设置滤波*/ CAN_MSEL(can_base) &= (~1); // CAN_MSEL(can_base) |= (1 << 2); /* Loopback Mode */ CAN_MSEL(can_base) |= (1 << 3);/* Single Filter */ bsp_int_vect_set(can_int_id, /* Assign ISR handler. */ 1u, /* 中断的优先级 */ 1u, /* 中断的目标CPU */ (void *)can_base, /* 参数 */ t113_can_irq_handle); irq_enable(can_int_id);// /* 使能中断 */ CAN_INTEN(can_base) = 0x0FF; } void can_send_data(uint32_t can_base,uint8_t * buf,int len) { CAN_CMD(can_base) |= (1 << 2); CAN_MSEL(can_base) &= (~1); int retry = 1000; do{ if(--retry == 0) break; }while(!(CAN_STA(can_base) & (1 << 2))); if(retry == 0) return;// uint32_t * des = &CAN_TRBUF0(can_base); for(int i = 0; i < len; i++) des[i] = buf[i]; //CAN_CMD(can_base) = (1 << 4); CAN_CMD(can_base) |= (1 << 0); } void can_read_data(uint32_t can_base,uint8_t * buf) { uint32_t * src = &CAN_TRBUF0(can_base); for(int i = 0; i < 13; i++) buf[i] = (char)src[i]; CAN_CMD(can_base) |= (1 << 2); } uint8_t can_teat_data[13] = { 8, 0, 0x80, 0x55, /* SFF - TX data byte 1 / EFF- ID[12:5] */ 0x55, /* SFF-TX data byte2[7:3] / EFF-ID[4:0] SFF-TX data byte2[2:0] */ 0x55, /* SFF-TX data byte 3 / EFF-TX data byte 1 */ 0x55, /* SDATA4_EDATA2 SFF-TX data byte 4 / EFF-TX data byte 2 */ 0x55, /* SDATA5_EDATA3 SFF-TX data byte 5 / EFF-TX data byte 3 */ 0x55,/* SDATA5_EDATA4 SFF-TX data byte 6 / EFF-TX data byte 4 */ 0x55,/* SDATA5_EDATA5 SFF-TX data byte 7 / EFF-TX data byte 5 */ 0x55,/* SDATA5_EDATA6 SFF-TX data byte 8 / EFF-TX data byte 6 */ 0x55, /* SDATA5_EDATA7 */ 0x55 /* SDATA5_EDATA8 */ }; /* can_id: is 0 or 1 */ void t113_can_test(void) { ini_can(0); ini_can(1); while(1) { can_send_data(CAN0,can_data); ms_delay(500); can_send_data(CAN1,can_data); ms_delay(500); } }
-
回复: T113裸跑不能产生中断请教:
@tripod9 我也是裸奔,没遇到这个问题。请教你裸奔,主频最高能跑到多少MHz?我这里最高就只能跑到800MHz,高于800M值,切换主频源时CPU就跑飞了。
-
请教T113运行主频的设置问题
使用芒果派小麻雀板的T113做测试,CPU运行主频高于800MHz,切换时就跑飞。测试代码如下,请求大佬们支招:
#define CPU_RUN_FREQ 1200000000 #define SYS_XTOSC_CLK 24000000 static void set_pll_cpux_axi(void) { uint32_t val; int n = (CPU_RUN_FREQ / SYS_XTOSC_CLK -1 ) & 0xFF; /* Switch to PLL_PERI(1X) clock while changing cpu pll (600MHz) */ CCU_CPU_AXI_CFG = (4<<24) ; sdelay(10000); /* cpu pll rate = 24000000 * n */ val = PLL_CPU_CTRL_REG & (~((0xff << 8) | (1 << 27))); val |= (n << 8); PLL_CPU_CTRL_REG = val; PLL_CPU_CTRL_REG &= ~(1 << 29); sdelay(5); PLL_CPU_CTRL_REG |= (1 << 29); sdelay(1000); while( (PLL_CPU_CTRL_REG &(1 << 28)) == 0 ); /* wait for pll lock */ PLL_CPU_CTRL_REG |= (1 << 27); /* open pll out gate */ sdelay(10000); /* Switch clock source */ CCU_CPU_AXI_CFG = (3 << 24); sdelay(10000); }
这一句CCU_CPU_AXI_CFG = (3 << 24)一执行,CPU就跑飞了.
请求支援。期待中。 -
回复: T113裸跑不能产生中断请教:
@mangogeek 在staru.s中添加下面一段后,中断就正常了。
/* Set vector base address register */
ldr r0, =__vector_table
mcr p15, 0, r0, c12, c0, 0
mrc p15, 0, r0, c1, c0, 0
bic r0, #(1 << 13)
mcr p15, 0, r0, c1, c0, 0/* Enable SMP mode for dcache, by setting bit 6 of auxiliary ctl reg */ mrc p15, 0, r0, c1, c0, 1 orr r0, r0, #(1 << 6) mcr p15, 0, r0, c1, c0, 1 /* enable branch prediction */ mrc p15, 0, r0, c1, c0, 0 orr r0, r0, #(1<<11) mcr p15, 0, r0, c1, c0, 0 /* Enable neon/vfp unit */ mrc p15, 0, r0, c1, c0, 2 orr r0, r0, #(0xf << 20) mcr p15, 0, r0, c1, c0, 2 isb mov r0, #0x40000000 vmsr fpexc, r0
-
T113裸跑不能产生中断请教:
T113就配置TIMER0做tick时钟:
#define TIMER_IRQ_CON_BASE (0x02050000) #define TIMER0_BASE (0x02050010) #define TIMER1_BASE (0x02050020) #define timer0 ((timer_t *)(TIMER0_BASE)) #define timer1 ((timer_t *)(TIMER1_BASE)) /* for R528/T113 */ #define T113_GIC_BASE (0x03021000) #define T113_CPUIF_BASE (0x03022000) #define PRESCALER_VALUE 1UL #define OS_CFG_TICK_RATE_HZ 1000 #define GPTIM_LOAD_CONST ((24000000 / OS_CFG_TICK_RATE_HZ) /(PRESCALER_VALUE) ) timer_irq_con_t * timer_irq_con = (timer_irq_con_t * )TIMER_IRQ_CON_BASE; void BSP_OS_TickInit (void) { timer0->INTV_VALUE = GPTIM_LOAD_CONST; timer0->CUR_VALUE = GPTIM_LOAD_CONST; bsp_int_vect_set(INT_TIMER0, /* Assign ISR handler. */ 1u, /* 中断的优先级 */ 3u, /* 中断的目标CPU */ 0u, /* 参数 */ BSP_OS_TickISR_Handler); /* 周期连续模式 */ timer0->CTRL_REG = (1 << 2); irq_enable(INT_TIMER0); timer_irq_con->TMR_IRQ_STA = 1;/*clear int sta */ timer_irq_con->TMR_IRQ_EN |= 1;/*enable timer0 int */ timer0->CTRL_REG |= 1;/*enable timer0 */ }
运行后timer0的计数正常,中断标志也已经置1了,但就是不产生中断。请教各位大佬,问题该如何定位。
gic模块的代码基本上是提取uboot的代码,代码在V3s上是能够正常运行的,只是迁移时根据T113的地址分布更改了各模块的基地址:
/* * (C) Copyright 2007-2013 * Allwinner Technology Co., Ltd. <www.allwinnertech.com> * Jerry Wang <wangflord@allwinnertech.com> * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include "v3s_map.h" #include "reg-ccu.h" #include "gic.h" #include "v3s_irq_id.h" #include <stdio.h> #include <stdint.h> #include "bsp_sys.h" struct _irq_handler { void *m_data; void (*m_func)( void * data); }; struct _irq_handler sunxi_int_handlers[NUMBER_OF_INT_VECTORS]@"OcramData"; /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void default_isr(void *data) { sysprintf("default_isr(): called from IRQ %d\n", (uint32_t)data); while(1); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int irq_enable(int irq_no) { uint32_t reg_val; uint32_t offset; if (irq_no >= NUMBER_OF_INT_VECTORS) { printf("irq NO.(%d) > NUMBER_OF_INT_VECTORS(%d) !!\n", irq_no, NUMBER_OF_INT_VECTORS); return -1; } if(irq_no == INT_NMI) { *(volatile unsigned int *)(0x01f00c00 + 0x10) |= 1; *(volatile unsigned int *)(0x01f00c00 + 0x40) |= 1; } offset = irq_no >> 5; // 除32 reg_val = readl(GIC_SET_EN(offset)); reg_val |= 1 << (irq_no & 0x1f); writel(reg_val, GIC_SET_EN(offset)); return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int irq_disable(int irq_no) { uint32_t reg_val; uint32_t offset; if (irq_no >= NUMBER_OF_INT_VECTORS) { sysprintf("irq NO.(%d) > NUMBER_OF_INT_VECTORS(%d) !!\n", irq_no, NUMBER_OF_INT_VECTORS); return -1; } if(irq_no == INT_NMI) { *(volatile unsigned int *)(0x01f00c00 + 0x10) |= 1; *(volatile unsigned int *)(0x01f00c00 + 0x40) &= ~1; } offset = irq_no >> 5; // 除32 reg_val = (1 << (irq_no & 0x1f)); writel(reg_val, GIC_CLR_EN(offset)); return 0; } void irq_int_prio_set (uint32_t int_id, uint32_t prio) { if (int_id >= NUMBER_OF_INT_VECTORS) { sysprintf("irq NO.(%d) > NUMBER_OF_INT_VECTORS(%d) !!\n", int_id, NUMBER_OF_INT_VECTORS); return ; } if (prio > BSP_INT_PRIO_LVL_MAX) { prio = BSP_INT_PRIO_LVL_MAX; return; } CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); // uint32_t * prio_r = (uint32_t *)GIC_SGI_PRIO((int_id>>5)); //prio_r[int_id] = (uint8_t)((prio << (8UL - __GIC_PRIO_BITS)) & (uint8_t)0xFFUL); uint32_t reg_val, addr, offset; /* dispatch the usb interrupt to CPU1 */ addr = GIC_SGI_PRIO(int_id>>2); reg_val = readl(addr); offset = 8 * (int_id & 3); reg_val &= ~(0xff<<offset); reg_val |= ((prio << (8UL - __GIC_PRIO_BITS)) << offset); writel(reg_val, addr); CPU_CRITICAL_EXIT(); } void irq_int_target_cpu_set (uint32_t int_id, uint8_t int_target_cpu) { if (int_id >= NUMBER_OF_INT_VECTORS) { sysprintf("irq NO.(%d) > NUMBER_OF_INT_VECTORS(%d) !!\n", int_id, NUMBER_OF_INT_VECTORS); return ; } CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); uint32_t reg_val, addr, offset; /* dispatch the usb interrupt to CPU1 */ addr = GIC_SGI_PROC_TARG(int_id>>2); reg_val = readl(addr); offset = 8 * (int_id & 3); reg_val &= ~(0xff<<offset); reg_val |= (int_target_cpu <<offset); writel(reg_val, addr); CPU_CRITICAL_EXIT(); return ; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void gic_sgi_handler(uint32_t irq_no) { sysprintf("SGI irq %d coming... \n", irq_no); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void gic_ppi_handler(uint32_t irq_no) { sysprintf("PPI irq %d coming... \n", irq_no); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void gic_spi_handler(uint32_t irq_no) { if (sunxi_int_handlers[irq_no].m_func != default_isr) { sunxi_int_handlers[irq_no].m_func(sunxi_int_handlers[irq_no].m_data); } } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void gic_clear_pending(uint32_t irq_no) { uint32_t reg_val; uint32_t offset; offset = irq_no >> 5; // 除32 reg_val = readl(GIC_PEND_CLR(offset)); reg_val |= (1 << (irq_no & 0x1f)); writel(reg_val, GIC_PEND_CLR(offset)); return ; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ void irq_install_handler (int irq, interrupt_handler_t handle_irq, void *data) { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); if (irq >= NUMBER_OF_INT_VECTORS || !handle_irq) { CPU_CRITICAL_EXIT(); return; } sunxi_int_handlers[irq].m_data = data; sunxi_int_handlers[irq].m_func = handle_irq; CPU_CRITICAL_EXIT(); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ void irq_free_handler(int irq) { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); if (irq >= NUMBER_OF_INT_VECTORS) { CPU_CRITICAL_EXIT(); return; } sunxi_int_handlers[irq].m_data = NULL; sunxi_int_handlers[irq].m_func = default_isr; CPU_CRITICAL_EXIT(); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ void BSP_IntHandler (void) { u32 idnum; idnum = readl(GIC_INT_ACK_REG); if ((idnum == 1023) ||(idnum == 1022)) { sysprintf("spurious irq !!\n"); return; } if (idnum >= NUMBER_OF_INT_VECTORS) { sysprintf("irq NO.(%d) > NUMBER_OF_INT_VECTORS(%d) !!\n", idnum, NUMBER_OF_INT_VECTORS-32); return; } // u32 int_cpu = (idnum >> 10) & 0x0f; if (idnum < 16) gic_sgi_handler(idnum); else if (idnum < 32) gic_ppi_handler(idnum); else gic_spi_handler(idnum); if(idnum == INT_NMI) { *(volatile unsigned int *)(0x01f00c00 + 0x10) |= 1; } writel(idnum, GIC_END_INT_REG);/*write GICC_EOIR, to cause priority drop on the GIC CPU interface*/ writel(idnum, GIC_DEACT_INT_REG);/* write to the GICC_DIR, to deactivate the interrupt*/ gic_clear_pending(idnum); return; } //#endif /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void gic_distributor_init(void) { uint32_t cpumask = 0x01010101; uint32_t gic_irqs; uint32_t i; writel(0, GIC_DIST_CON); /* check GIC hardware configutation */ gic_irqs = ((readl(GIC_CON_TYPE) & 0x1f) + 1) * 32; if (gic_irqs > 1020) { gic_irqs = 1020; } if (gic_irqs < NUMBER_OF_INT_VECTORS) { sysprintf("GIC parameter config error, only support %d" " irqs < %d(spec define)!!\n", gic_irqs, NUMBER_OF_INT_VECTORS); return ; } /* set trigger type to be level-triggered, active low */ for (i=0; i<NUMBER_OF_INT_VECTORS; i+=16) { writel(0, GIC_IRQ_MOD_CFG(i>>4)); } /* set priority */ for (i=GIC_SRC_SPI(0); i<NUMBER_OF_INT_VECTORS; i+=4) { writel(0xffffffff, GIC_SPI_PRIO((i-32)>>2)); } /* set processor target */ for (i=32; i<NUMBER_OF_INT_VECTORS; i+=4) { writel(cpumask, GIC_SPI_PROC_TARG((i-32)>>2)); } /* disable all interrupts */ for (i=32; i<NUMBER_OF_INT_VECTORS; i+=32) { writel(0xffffffff, GIC_CLR_EN(i>>5)); } /* clear all interrupt active state */ for (i=32; i<NUMBER_OF_INT_VECTORS; i+=32) { writel(0xffffffff, GIC_ACT_CLR(i>>5)); } writel(1, GIC_DIST_CON); return ; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void gic_cpuif_init(void) { uint32_t i; writel(0, GIC_CPU_IF_CTRL); /* * Deal with the banked PPI and SGI interrupts - disable all * PPI interrupts, ensure all SGI interrupts are enabled. */ writel(0xffff0000, GIC_CLR_EN(0)); writel(0x0000ffff, GIC_SET_EN(0)); /* Set priority on PPI and SGI interrupts */ for (i=0; i<16; i+=4) { writel(0xffffffff, GIC_SGI_PRIO(i>>2)); } for (i=16; i<32; i+=4) { writel(0xffffffff, GIC_PPI_PRIO((i-16)>>2)); } /* Priority level is implementation defined. To determine the number of priority bits implemented write 0xFF to an IPRIORITYR priority field and read back the value stored.*/ // GIC_SetPriority((IRQn_Type)0U, 0xFFU); //priority_field = GIC_GetPriority((IRQn_Type)0U); writel(0xff, GIC_INT_PRIO_MASK); writel(1, GIC_CPU_IF_CTRL); return ; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int arch_interrupt_init (void) { int i; for (i=0; i<NUMBER_OF_INT_VECTORS; i++) { sunxi_int_handlers[i].m_func = default_isr; } gic_distributor_init(); gic_cpuif_init(); return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int arch_interrupt_exit(void) { gic_distributor_init(); gic_cpuif_init(); return 0; } void bsp_int_vect_set( uint32_t int_id, uint32_t int_prio, uint8_t int_target_list, void * pParam, system_irq_handler_t int_fnct) { irq_install_handler (int_id, int_fnct, pParam); irq_int_prio_set(int_id,int_prio); irq_int_target_cpu_set(int_id,int_target_list); }