#include #include #include #ifdef CONFIG_AR9 volatile unsigned int *BCU_CON_Register = (volatile unsigned int *)(0xBE100000 + 0x10); volatile unsigned int *BCU_ECON_Register = (volatile unsigned int *)(0xBE100000 + 0x14); volatile unsigned int *BCU_EADD_Register = (volatile unsigned int *)(0xBE100000 + 0x20); volatile unsigned int *BCU_EDAT_Register = (volatile unsigned int *)(0xBE100000 + 0x24); volatile unsigned int *BCU_IRNEN_Register = (volatile unsigned int *)(0xBE100000 + 0xF4); /*------------------------------------------------------------------------------------------*\ * LANTIQ: * * Von der Entwicklung wurde bestätigt, dass die beiden Offsets der Register IRNICR und * IRNCR vertauscht sind, d.h. der Interrupt wird durch Schreiben auf Offset 0xF8 quittiert, * und nicht auf Offset 0xFC, wie in der Registerbeschreibung angegeben. * * Wie bestätigen Sie in Ihrer SW diesen Interrupt? * Vielleicht wird er ja nicht richtig quittiert, * sondern wegen der fehlerhaften Dokumentation neu gesetzt. \*------------------------------------------------------------------------------------------*/ /*--- volatile unsigned int *BCU_IRNICR_Register = (volatile unsigned int *)(0xBE100000 + 0xF8); ---*/ /*--- volatile unsigned int *BCU_IRNCR_Register = (volatile unsigned int *)(0xBE100000 + 0xFC); ---*/ volatile unsigned int *BCU_IRNCR_Register = (volatile unsigned int *)(0xBE100000 + 0xF8); volatile unsigned int *BCU_IRNICR_Register = (volatile unsigned int *)(0xBE100000 + 0xFC); #else /*--- #ifdef CONFIG_AR9 ---*/ volatile unsigned int *BCU_CON_Register = (volatile unsigned int *)(0xBE100000 + 0x10); volatile unsigned int *BCU_ECON_Register = (volatile unsigned int *)(0xBE100000 + 0x20); volatile unsigned int *BCU_EADD_Register = (volatile unsigned int *)(0xBE100000 + 0x24); volatile unsigned int *BCU_EDAT_Register = (volatile unsigned int *)(0xBE100000 + 0x28); volatile unsigned int *BCU_IRNEN_Register = (volatile unsigned int *)(0xBE100000 + 0xF4); /*------------------------------------------------------------------------------------------*\ * LANTIQ: * * Von der Entwicklung wurde bestätigt, dass die beiden Offsets der Register IRNICR und * IRNCR vertauscht sind, d.h. der Interrupt wird durch Schreiben auf Offset 0xF8 quittiert, * und nicht auf Offset 0xFC, wie in der Registerbeschreibung angegeben. * * Wie bestätigen Sie in Ihrer SW diesen Interrupt? * Vielleicht wird er ja nicht richtig quittiert, * sondern wegen der fehlerhaften Dokumentation neu gesetzt. \*------------------------------------------------------------------------------------------*/ /*--- volatile unsigned int *BCU_IRNICR_Register = (volatile unsigned int *)(0xBE100000 + 0xF8); ---*/ /*--- volatile unsigned int *BCU_IRNCR_Register = (volatile unsigned int *)(0xBE100000 + 0xFC); ---*/ volatile unsigned int *BCU_IRNCR_Register = (volatile unsigned int *)(0xBE100000 + 0xF8); volatile unsigned int *BCU_IRNICR_Register = (volatile unsigned int *)(0xBE100000 + 0xFC); #endif /*--- #else ---*/ /*--- #ifdef CONFIG_AR9 ---*/ #define BCU_IRQ_ACK() while(*BCU_IRNCR_Register) { *BCU_IRNCR_Register = 1; wmb(); } volatile unsigned int *sBCU_CON_Register = (volatile unsigned int *)(0xBC200400 + 0x10); volatile unsigned int *sBCU_ECON_Register = (volatile unsigned int *)(0xBC200400 + 0x20); volatile unsigned int *sBCU_EADD_Register = (volatile unsigned int *)(0xBC200400 + 0x24); volatile unsigned int *sBCU_EDAT_Register = (volatile unsigned int *)(0xBC200400 + 0x28); volatile unsigned int *sBCU_IRNEN_Register = (volatile unsigned int *)(0xBC200400 + 0xF4); volatile unsigned int *sBCU_IRNICR_Register = (volatile unsigned int *)(0xBC200400 + 0xF8); volatile unsigned int *sBCU_IRNCR_Register = (volatile unsigned int *)(0xBC200400 + 0xFC); volatile unsigned int *sBIU_FPISCR_Register = (volatile unsigned int *)(0xBF880000 + 0x2D8); volatile unsigned int *sBIU_FPISSR_Register = (volatile unsigned int *)(0xBF880000 + 0x2E0); volatile unsigned int *sBIU_FBCFG_Register = (volatile unsigned int *)(0xBF880000 + 0x2e8); volatile unsigned int *sBIU_AHBCR_Register = (volatile unsigned int *)(0xBF880000 + 0x2f0); volatile unsigned int *sBIU_AHBSR_Register = (volatile unsigned int *)(0xBF880000 + 0x2f8); #define CSS_BASE 0xBF400000 #define CSS_ID (volatile unsigned int *)(CSS_BASE + 0x0) #define CSS_IRN_FLAG_ti_ppe_cerr (1 << 11) #define CSS_IRN_FLAG_ti_ppe_werr (1 << 10) #define CSS_IRN_FLAG_ti_ahb3s_cerr (1 << 9) #define CSS_IRN_FLAG_ti_ahb3s_werr (1 << 8) #define CSS_IRN_FLAG_ti_ahb1s_cerr (1 << 7) #define CSS_IRN_FLAG_ti_ahb1s_werr (1 << 6) #define CSS_IRN_FLAG_ti_ocps_cerr (1 << 5) #define CSS_IRN_FLAG_ti_ocps_werr (1 << 4) #define CSS_IRN_FLAG_ti_fpi1s_cerr (1 << 3) #define CSS_IRN_FLAG_ti_fpi1s_werr (1 << 2) #define CSS_IRN_FLAG_ti_sais_cerr (1 << 1) #define CSS_IRN_FLAG_ti_sais_werr (1 << 0) #define CSS_IRN_FLAG_ALL ((1 << 12) - 1) /*--- CPU Subsystem Interrupt Node Enable ---*/ #define CSS_IRN_EN (volatile unsigned int *)(CSS_BASE + 0x200) /*--- CPU Subsystem Interrupt Node Control w clear irq-request---*/ #define CSS_IRN_CR (volatile unsigned int *)(CSS_BASE + 0x208) /*--- CPU Subsystem Interrupt Node Capture Register ---*/ #define CSS_IRN_ICR (volatile unsigned int *)(CSS_BASE + 0x210) #define DDR_GSR0_FLAG_p5busy (1 << 13) #define DDR_GSR0_FLAG_p4busy (1 << 12) #define DDR_GSR0_FLAG_p3busy (1 << 11) #define DDR_GSR0_FLAG_p2busy (1 << 10) #define DDR_GSR0_FLAG_p1busy (1 << 9) #define DDR_GSR0_FLAG_p0busy (1 << 8) #define DDR_GSR0_FLAG_qaf (1 << 4) #define DDR_GSR0_FLAG_cbusy (1 << 3) #define DDR_GSR0_FLAG_rip (1 << 2) #define DDR_GSR0_FLAG_cke (1 << 1) #define DDR_GSR0_FLAG_sra (1 << 0) #define DDR_GSR0 (volatile unsigned int *)(CSS_BASE + 0x400) #define DDR_GCR0 (volatile unsigned int *)(CSS_BASE + 0x408) #define DDR_GCR1_FLAG_ck (1 << 5) #define DDR_GCR1_FLAG_ca (1 << 4) #define DDR_GCR1_FLAG_ds3 (1 << 3) #define DDR_GCR1_FLAG_ds2 (1 << 2) #define DDR_GCR1_FLAG_ds1 (1 << 1) #define DDR_GCR1_FLAG_ds0 (1 << 0) #define DDR_GCR1 (volatile unsigned int *)(CSS_BASE + 0x410) #define DDR_PRIO_TI (volatile unsigned int *)(CSS_BASE + 0x418) #define DDR_BASE 0xBF401000 #define DDR_CCR09_ODT_RD_MAP_CS0_SHIFT 24 #define DDR_CCR09_MAX_CS_REG_SHIFT 16 #define DDR_CCR09_LOWPOWER_REFRESH_ENABLE_SHIFT 8 #define DDR_CCR09_DRAM_CLK_DISABLE_SHIFT 0 #define DDR_CCR09 (volatile unsigned int *)(DDR_BASE + 0x90) /**--------------------------------------------------------------------------------**\ \**--------------------------------------------------------------------------------**/ struct _bcu_irq { unsigned int irq; const char *name; void (*init)(void); void (*show_info)(int irq, const struct _bcu_irq *pbcu); /*--- irq != 0: inklusive ack ---*/ }; /**--------------------------------------------------------------------------------**\ \**--------------------------------------------------------------------------------**/ static void init_BCU(void) { printk(KERN_ERR"%s: %8x\n", __func__, *BCU_CON_Register); *BCU_CON_Register = (0xffff << 0) | /* BCU But Time Out, default 0xFFFF */ (1 << 16) | /* BCU Debug Trace Enable, default ON */ /*--- (1 << 17) | ---*//* BCU Arbiter Priority Mode, default 0 (fixed) */ /*--- (1 << 18) | ---*//* BCU Power Savin Enable (Automatic Clock Control), default OFF, 0 */ (1 << 19) | /* Starvation protection, default ON, 1 */ (0x40 << 24) | /* Starvation Counter */ 0; BCU_IRQ_ACK(); *BCU_IRNEN_Register = 1; wmb(); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void show_BCU_info(int irq, const struct _bcu_irq *pbcu) { unsigned int ErrorDataInfo = *BCU_ECON_Register; unsigned int ErrorAddrInfo = *BCU_EADD_Register; unsigned int ErrorDataCapture = *BCU_EDAT_Register; if((irq == 0) && (((ErrorDataInfo >> 28) & 0xF) == 0x0)) { return; } if(irq == pbcu->irq) { printk(KERN_ERR "[%s] 'FPI Master Bus BCU' Error Interrupt\n", __func__); } printk(KERN_ERR "BCU[BCU_EADD]: Error Address Register: 0x%08x\n", ErrorAddrInfo); printk(KERN_ERR "BCU[BCU_EDAT]: Error Data Capture Register: 0x%08x\n", ErrorDataCapture); printk(KERN_ERR "BCU[BCU_CON] : Control Register: 0x%08x\n", *BCU_CON_Register); printk(KERN_ERR "BCU[BCU_ECON]: Error Register (0x%08x):" "\n\tFPI Bus Operation Code 0x%x " "\n\tFPI Bus Tag Number 0x%x " "\n\tFPI Bus Read Signal: %s " "\n\tFPI Bus Write Signal: %s " "\n\tFPI Bus Supervisor Mode: %s " "\n\tFPI Bus Acknowledge Signal: 0x%x " "\n\tFPI Bus Abort: %s " "\n\tFPI Bus Ready: %s " "\n\tFPI Bus Timeout: %s " "\n\tFPI Bus Error Counter: %d\n", ErrorDataInfo, (ErrorDataInfo >> 28) & ((1 << 4) - 1), (ErrorDataInfo >> 24) & ((1 << 4) - 1), (ErrorDataInfo & (1 << 23)) ? "passive" : "active", (ErrorDataInfo & (1 << 22)) ? "passive" : "active", (ErrorDataInfo & (1 << 21)) ? "active" : "passive", (ErrorDataInfo >> 19) & ((1 << 2) - 1), (ErrorDataInfo & (1 << 18)) ? "passive" : "active", (ErrorDataInfo & (1 << 17)) ? "active" : "passive", (ErrorDataInfo & (1 << 16)) ? "occurred" : "not pressed", (ErrorDataInfo >> 0) & ((1 << 16) - 1) ); if(irq == pbcu->irq) { BCU_IRQ_ACK(); wmb(); } } /**--------------------------------------------------------------------------------**\ \**--------------------------------------------------------------------------------**/ static void init_sBCU(void) { printk(KERN_ERR"%s: %8x\n", __func__, *sBCU_CON_Register); *sBCU_CON_Register = (0xffff << 0) | /* Slave BCU But Time Out, default 0xFFFF */ (1 << 16) | /* Slave BCU Debug Trace Enable, default ON */ /*--- (1 << 18) | ---*/ /* Slave BCU Power Savin Enable (Automatic Clock Control), default OFF, 0 */ (1 << 19) | /* Starvation protection, default ON, 1 */ (0x40 << 24) | /* Starvation Counter */ 0; *sBCU_IRNCR_Register = 0; *sBCU_IRNEN_Register = 1; wmb(); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void show_sBCU_info(int irq, const struct _bcu_irq *pbcu) { unsigned int ErrorDataInfo = *sBCU_ECON_Register; unsigned int ErrorAddrInfo = *sBCU_EADD_Register; unsigned int ErrorDataCapture = *sBCU_EDAT_Register; if((irq == 0) && (((ErrorDataInfo >> 28) & 0xF) == 0xF)) { return; } if(irq == pbcu->irq) { printk(KERN_ERR "[%s] 'FPI Slave BCU0' Error Interrupt\n", __func__); } printk(KERN_ERR "Slave BCU[sBCU_EADD]: Error Address Register: 0x%08x\n", ErrorAddrInfo); printk(KERN_ERR "Slave BCU[sBCU_EDAT]: Error Data Capture Register: 0x%08x\n", ErrorDataCapture); printk(KERN_ERR "Slave BCU[sBCU_CON] : Control Register: 0x%08x\n", *sBCU_CON_Register); printk(KERN_ERR "Slave BCU[sBCU_CON] : IRNCR_Register: 0x%08x\n", *sBCU_IRNCR_Register ); printk(KERN_ERR "Slave BCU[sBCU_ECON]: Error Register (0x%08x):" "\n\tFPI Bus Operation Code 0x%x " "\n\tFPI Bus Tag Number 0x%x " "\n\tFPI Bus Read Signal: %s " "\n\tFPI Bus Write Signal: %s " "\n\tFPI Bus Supervisor Mode: %s " "\n\tFPI Bus Acknowledge Signal: 0x%x " "\n\tFPI Bus Abort: %s " "\n\tFPI Bus Ready: %s " "\n\tFPI Bus Timeout: %s " "\n\tFPI Bus Error Counter: %d\n", ErrorDataInfo, (ErrorDataInfo >> 28) & ((1 << 4) - 1), (ErrorDataInfo >> 24) & ((1 << 4) - 1), (ErrorDataInfo & (1 << 23)) ? "passive" : "active", (ErrorDataInfo & (1 << 22)) ? "passive" : "active", (ErrorDataInfo & (1 << 21)) ? "active" : "passive", (ErrorDataInfo >> 19) & ((1 << 2) - 1), (ErrorDataInfo & (1 << 18)) ? "passive" : "active", (ErrorDataInfo & (1 << 17)) ? "active" : "passive", (ErrorDataInfo & (1 << 16)) ? "occurred" : "not pressed", (ErrorDataInfo >> 0) & ((1 << 16) - 1) ); if(irq == pbcu->irq) { *sBCU_IRNCR_Register = 0; wmb(); } } /**--------------------------------------------------------------------------------**\ \**--------------------------------------------------------------------------------**/ static void init_sBIU(void) { } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void show_sBIU_info(int irq, const struct _bcu_irq *pbcu) { unsigned int Status = *sBIU_AHBSR_Register ; if(irq == pbcu->irq) { printk(KERN_ERR "[%s]SBIU Error Interrupt\n", __func__); } printk(KERN_ERR "[%s] BIU AHB Status Register: 0x%08x\n", __func__, Status); } /**--------------------------------------------------------------------------------**\ \**--------------------------------------------------------------------------------**/ static void init_XBAR(void) { *CSS_IRN_EN = CSS_IRN_FLAG_ALL; } /**--------------------------------------------------------------------------------**\ \**--------------------------------------------------------------------------------**/ static void show_XBAR_info(int irq, const struct _bcu_irq *pbcu) { unsigned int irqcr = *CSS_IRN_CR; if(irq == pbcu->irq) { printk(KERN_ERR "[%s] 'XBAR Error Interrupt\n", __func__); } printk(KERN_ERR "[%s] CSS_IRN_CR %08x\n" "\t DDR_GSR0 %08x\n" "\t DDR_GCR0 %08x\n" "\t DDR_GCR1 %08x\n" "\t DDR_PRIO_TI %08x\n", __func__, irqcr, *DDR_GSR0, *DDR_GCR0, *DDR_GCR1, *DDR_PRIO_TI); if(irq == pbcu->irq) { *CSS_IRN_CR = irqcr; wmb(); } } /**--------------------------------------------------------------------------------**\ \**--------------------------------------------------------------------------------**/ static const struct _bcu_irq bcu_irq[] = { { irq: INT_NUM_IM0_IRL25, name: "CosBCU_IR", init: init_BCU, show_info: show_BCU_info }, { irq: INT_NUM_IM1_IRL25, name: "BCU0_IR", init: init_sBCU, show_info: show_sBCU_info }, { irq: INT_NUM_IM4_IRL23, name: "XBARERR_IR", init: init_XBAR, show_info: show_XBAR_info }, /*--- { irq: INT_NUM_IM3_IRL28 , name: "MC_IR" }, ---*/ /*--- { irq: INT_NUM_IM0_IRL22 , name: "EBU_IR" }, ---*/ { irq: INT_NUM_IM1_IRL27, name: "SBIU_ERRIR", init: init_sBIU, show_info: show_sBIU_info }, }; /**--------------------------------------------------------------------------------**\ \**--------------------------------------------------------------------------------**/ void bcu_show(void) { int i; for(i = 0; i < ARRAY_SIZE(bcu_irq); i++) { if(bcu_irq[i].show_info) { bcu_irq[i].show_info(0, &bcu_irq[i]); } } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static irqreturn_t bcu_control_interrupt(int irq, void *context __attribute__ ((unused))) { int i, ret = 0; for(i = 0; i < ARRAY_SIZE(bcu_irq); i++) { /*--- if(bcu_irq[i].irq == irq) { ---*/ if(bcu_irq[i].show_info) { bcu_irq[i].show_info(irq, &bcu_irq[i]); } ret = IRQ_HANDLED; /*--- } ---*/ } /*--- console_verbose(); ---*/ /*--- dump_stack(); ---*/ if(ret != IRQ_HANDLED) { printk(KERN_ERR"%s: unhandled irq=%u\n", __func__, irq); } return IRQ_HANDLED; } /**--------------------------------------------------------------------------------**\ \**--------------------------------------------------------------------------------**/ void self_refresh_init(void) { unsigned int val = *DDR_CCR09; printk("%s: %x ODT_RD_MAP=%x MAX_CS_REG=%x LOWPOWER_REFRESH_ENA=%x DRAM_CLK_DIS=%x\n", __func__, val, (val >> DDR_CCR09_ODT_RD_MAP_CS0_SHIFT) & 0x3, (val >> DDR_CCR09_MAX_CS_REG_SHIFT) & 0x3, (val >> DDR_CCR09_LOWPOWER_REFRESH_ENABLE_SHIFT) & 0x3, (val >> DDR_CCR09_DRAM_CLK_DISABLE_SHIFT ) & 0x3); val |= (1 << DDR_CCR09_LOWPOWER_REFRESH_ENABLE_SHIFT); *DDR_CCR09 = val; wmb(); } EXPORT_SYMBOL(self_refresh_init); /**--------------------------------------------------------------------------------**\ \**--------------------------------------------------------------------------------**/ void self_refresh_exit(void) { unsigned int val = *DDR_CCR09; val &= ~(0x3 << DDR_CCR09_LOWPOWER_REFRESH_ENABLE_SHIFT); *DDR_CCR09 = val; } EXPORT_SYMBOL(self_refresh_exit); #define start_addr 0xA0000000 #define end_addr (0xA0000000 + (256 << 20)) #define row_cnt (1 << 14) #define col_cnt (1 << 10) #define refreshtime_ms 16 #define rows_per_125us (row_cnt / (refreshtime_ms * 8)) static unsigned int act_addr = start_addr; /**--------------------------------------------------------------------------------**\ \**--------------------------------------------------------------------------------**/ void self_refresh(void) { unsigned int loop = rows_per_125us; while(loop--) { *((volatile unsigned short *)(act_addr)); act_addr += col_cnt; if(act_addr >= end_addr) { /*--- printk(KERN_ERR"%s\n", __func__); ---*/ act_addr = start_addr; } } } EXPORT_SYMBOL(self_refresh); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int bcu_control_init(void) { int i, ret; for(i = 0; i < ARRAY_SIZE(bcu_irq); i++) { if(bcu_irq[i].init) { bcu_irq[i].init(); } ret = request_irq(bcu_irq[i].irq, bcu_control_interrupt, IRQF_DISABLED, bcu_irq[i].name, NULL); if(ret < 0) { printk(KERN_ERR "[%s] request irq %s (%d) failed\n", __func__, bcu_irq[i].name, bcu_irq[i].irq); } } printk(KERN_ERR "[%s] interrupts for BCU installed\n", __func__); return 0; } device_initcall(bcu_control_init);