📄 em86xxapi.c
字号:
/* if the interrupt is detected by edge detector not level detector */ \ /* clear edge status */ \ if ((IRQMASKOF(irq) & (IRQMASK_RISINGEDGE | IRQMASK_FALLINGEDGE)) != 0) \ __raw_writel(reg, REG_BASE_CPU + CPU_edge_rawstat); \ } #define EM86XX_X_UNMASK(x) \ void em86xx_unmask_##x##(unsigned int irq) \ { \ unsigned int reg; \ \ /* IRQ / FIQ enable */ \ reg = (1 << irq); \ __raw_writel(reg, REG_BASE_CPU + CPU_##x##_enableset); \ }#define EM86XX_X_STATUS(x) \ int em86xx_##x##_status(unsigned int irq) \ { \ unsigned int status = __raw_readl(REG_BASE_CPU + CPU_##x##_rawstat); \ \ return (status & IRQMASKOF(irq)) ? 1 : 0; \ }#define EM86XX_X_WAIT(x) \ void em86xx_##x##_wait(unsigned int irq) \ { \ unsigned int mask = IRQMASKOF(irq); \ \ while ((__raw_readl(REG_BASE_CPU + CPU_##x##_rawstat) & mask) == 0) \ ; \ }EM86XX_X_MASK(irq)EM86XX_X_UNMASK(irq)EM86XX_X_STATUS(irq)EM86XX_X_WAIT(irq)EM86XX_X_MASK(fiq)EM86XX_X_UNMASK(fiq)EM86XX_X_STATUS(fiq)EM86XX_X_WAIT(fiq)// // interrupt handler//static struct { irq_handler_t handler; void *pdata;} s_irq_info[NR_IRQS];void em86xx_sti(void){ unsigned int cpsr_reg; __asm__ __volatile__( "mrs %0, cpsr\n" // get CPSR "bic %0, %0, #0x80\n" // enable IRQ "msr cpsr_c, %0\n" // set CPSR : "=r" (cpsr_reg) : : "memory");}void em86xx_cli(void){ unsigned int cpsr_reg; __asm__ __volatile__( "mrs %0, cpsr\n" // get CPSR "orr %0, %0, #0x80\n" // disable IRQ "msr cpsr_c, %0\n" // set CPSR : "=r" (cpsr_reg) : : "memory");}int em86xx_irqenabled(void){ unsigned int cpsr_reg; __asm__ __volatile__( "mrs %0, cpsr\n" // get CPSR : "=r" (cpsr_reg)); return (cpsr_reg & 0x80) ? 0 : 1;}void em86xx_request_irq(int irq, irq_handler_t handler, void *pdata){ s_irq_info[irq].handler = handler; s_irq_info[irq].pdata = pdata; em86xx_unmask_irq(irq);}void em86xx_free_irq(int irq){ em86xx_mask_irq(irq); s_irq_info[irq].handler = NULL; s_irq_info[irq].pdata = NULL;}void em86xx_irq_handler(void){ int i; unsigned int mask; unsigned int status = __raw_readl(REG_BASE_CPU + CPU_irq_status); for (i = 0, mask = 1; status != 0; ++i, mask <<= 1) { if (status & mask) { status &= ~mask; em86xx_mask_irq(i); /* If no handler, left it masked */ if (s_irq_info[i].handler) { s_irq_info[i].handler(i, s_irq_info[i].pdata); em86xx_unmask_irq(i); } } }}// // fast interrupt handler//static struct { fiq_handler_t handler; void *pdata;} s_fiq_info[NR_IRQS];void em86xx_stf(void){ unsigned int cpsr_reg; __asm__ __volatile__( "mrs %0, cpsr\n" // get CPSR "bic %0, %0, #0x40\n" // enable FIQ "msr cpsr_c, %0\n" // set CPSR : "=r" (cpsr_reg) : : "memory");}void em86xx_clf(void){ unsigned int cpsr_reg; __asm__ __volatile__( "mrs %0, cpsr\n" // get CPSR "orr %0, %0, #0x40\n" // disable FIQ "msr cpsr_c, %0\n" // set CPSR : "=r" (cpsr_reg) : : "memory");}void em86xx_request_fiq(int fiq, fiq_handler_t handler, void *pdata){ s_fiq_info[fiq].handler = handler; s_fiq_info[fiq].pdata = pdata; em86xx_unmask_fiq(fiq);}void em86xx_free_fiq(int fiq){ em86xx_mask_fiq(fiq); s_fiq_info[fiq].handler = NULL; s_fiq_info[fiq].pdata = NULL;}void em86xx_fiq_handler(void){ int i; unsigned int mask; unsigned int status = __raw_readl(REG_BASE_CPU + CPU_fiq_status); for (i = 0, mask = 1; status != 0; ++i, mask <<= 1) { if (status & mask) { status &= ~mask; em86xx_mask_fiq(i); /* If no handler, left it masked */ if (s_fiq_info[i].handler) { s_fiq_info[i].handler(i, s_fiq_info[i].pdata); em86xx_unmask_fiq(i); } } }}//// Switcbox (Host interface)//static int g_sbox_map[SBOX_MAX + 1];static int g_sbox_used[2], g_sbox_lastmap[2];// Initialize SwitchBox int em86xx_sbox_init(void){#ifdef CONFIG_ARCH_MAMBO em86xx_sbox_setup(SBOX_IDEFLASH, SBOX_PCIMASTER);#else#ifdef CONFIG_ENABLE_IDE_BM em86xx_sbox_setup(SBOX_IDEDVD, SBOX_PCIMASTER);#else em86xx_sbox_setup(SBOX_IDEFLASH, SBOX_PCIMASTER);#endif#endif em86xx_sbox_reset(); return 0;}void em86xx_sbox_reset(void){#if defined(CONFIG_ARCH_MAMBO) __raw_writel(0x1f1f1f1f, REG_BASE_HOST + SBOX_reset); __raw_writel(0x1f001f00, REG_BASE_HOST + SBOX_reset);#elif defined(CONFIG_ARCH_TANGO) __raw_writel(0x7f7fffff, REG_BASE_HOST + SBOX_reset); __raw_writel(0x7f00ff00, REG_BASE_HOST + SBOX_reset);#endif}// connect R0/W0 and R1/W1 to specified interface if0, if1int em86xx_sbox_setup(int if0, int if1){ int i; unsigned int data;#if defined(CONFIG_ARCH_MAMBO) g_sbox_map[0] = if0; g_sbox_map[1] = if1; g_sbox_map[SBOX_IDEFLASH] = 7; g_sbox_map[SBOX_PCIMASTER] = 7; g_sbox_map[SBOX_PCISLAVE] = 7; g_sbox_map[if0] = 0; g_sbox_map[if1] = 1;#elif defined(CONFIG_ARCH_TANGO) g_sbox_map[0] = if0 + 1; g_sbox_map[1] = if1 + 1; g_sbox_map[SBOX_PCIMASTER] = 0xf; g_sbox_map[SBOX_PCISLAVE] = 0xf; g_sbox_map[SBOX_CIPHER] = 0xf; g_sbox_map[SBOX_IDEDVD] = 0xf; g_sbox_map[SBOX_IDEFLASH] = 0xf; g_sbox_map[SBOX_SFLASH] = 0xf; g_sbox_map[if0] = 1; g_sbox_map[if1] = 2;#else#error Unknown Architecture#endif for (i = SBOX_MAX, data = 0; i >= 0; --i) data = (data << 4) | g_sbox_map[i]; __raw_writel(data, REG_BASE_HOST + SBOX_route); return 0;}int em86xx_sbox_connect(int iface){ int port = -1;#if defined(CONFIG_ARCH_MAMBO) if (iface == g_sbox_map[0]) port = 0; else if (iface == g_sbox_map[1]) port = 1;#elif defined(CONFIG_ARCH_TANGO) if (iface + 1 == g_sbox_map[0]) port = 0; else if (iface + 1 == g_sbox_map[1]) port = 1;#else#error Unknown Architecture#endif else { uart_printf("SBOX : Can't assign a channel\n");#if 0 int i, firstavail; // check if last used slot is available for (i = 0; i < 2; ++i) { if (g_sbox_lastmap[i] == iface && !g_sbox_used[i]) { port = i; break; } } // look for first available slot if (port < 0) { for (i = 0, firstavail = -1; i < 2; ++i) { if (!g_sbox_used[i]) { if (firstavail < 0) firstavail = i; if (g_sbox_lastmap[i] == 0) { port = i; break; } } } if (port < 0) port = firstavail; } if (port >= 0) { g_sbox_map[port] = iface; em86xx_sbox_setup(g_sbox_map[0], g_sbox_map[1]); }#endif } if (port >= 0) { g_sbox_used[port] = 1; g_sbox_lastmap[port] = iface; } return port;}void em86xx_sbox_disconnect(int port){ if (port >= 0) g_sbox_used[port] = 0;}// // MBUS interface//unsigned int em86xx_mbus_init(void){ return 0;}// sbox : SBOX_xxx// fromdev : // 0 : EM86XX => device (writing) : use Wx port// 1 : device => EM86XX (reading) : use Rx portunsigned int em86xx_mbus_alloc_dma(int sbox, int fromdev, unsigned int *pregbase, int *pirq){ int port = em86xx_sbox_connect(sbox); if (pirq) *pirq = IRQ_MBUS_W0 + port + ((fromdev) ? 0 : 2); if (pregbase) { *pregbase = REG_BASE_HOST + MIF_w0_base; if (!fromdev) *pregbase += 0x80; *pregbase += port * 0x40; } return port;}void em86xx_mbus_free_dma(int port){ em86xx_sbox_disconnect(port);}void em86xx_mbus_setup_dma_linear(unsigned int regbase, unsigned int addr, unsigned int count){ __raw_writel(addr, regbase + 0x00); __raw_writel(count, regbase + 0x04); __raw_writel(0x05, regbase + 0x0c);}void em86xx_mbus_setup_dma_double(unsigned int regbase, unsigned int addr, unsigned int count, unsigned int addr2, unsigned int count2){ __raw_writel(addr, regbase + 0x00); __raw_writel((count2 << 16) | count, regbase + 0x04); __raw_writel(addr2, regbase + 0x08); __raw_writel(0x06, regbase + 0x0c);}void em86xx_mbus_setup_dma_rectangle(unsigned int regbase, unsigned int addr, unsigned int horiz, unsigned int lines, int skip){ __raw_writel(addr, regbase + 0x00); __raw_writel((lines << 16) | horiz, regbase + 0x04); __raw_writel(horiz, regbase + 0x08); __raw_writel(0x07, regbase + 0x0c);}#define MBUS_LINEAR_MAX (0x2000 - 0x200)int em86xx_mbus_setup_dma(unsigned int regbase, unsigned int addr, unsigned int count){ if ((__raw_readl(regbase + MIF_cmd_offset) & 0x07) != 0) { uart_printf("MBUS error : previous command is pending\n"); return 1; } if (count <= MBUS_LINEAR_MAX) { // try linear // uart_printf("Linear\n"); em86xx_mbus_setup_dma_linear(regbase, addr, count); } else if (count <= (MBUS_LINEAR_MAX * 2)) { // try double // uart_printf("Double (%04x, %04x)\n", MBUS_LINEAR_MAX, count - MBUS_LINEAR_MAX); em86xx_mbus_setup_dma_double(regbase, addr, MBUS_LINEAR_MAX, addr + MBUS_LINEAR_MAX, count - MBUS_LINEAR_MAX); } else { int i, horiz, lines; // try rectangle for (i = 0, horiz = 1; i < 10 && ((count & 0x01) == 0); ++i, horiz <<= 1) ; lines = count >> i; if (horiz > MBUS_LINEAR_MAX || lines > MBUS_LINEAR_MAX) { uart_printf("MBUS error : too big to transfer (%d, %d)\n", horiz, lines); return 1; } // uart_printf("Rectangle (%d x %d)\n", horiz, lines); em86xx_mbus_setup_dma_rectangle(regbase, addr, horiz, lines, horiz); } return 0;}void em86xx_mbus_wait(unsigned int regbase){ while (__raw_readl(regbase + MIF_cmd_offset) != 0) ;}//// PCI Master//void em86xx_pcimaster_setup_read(unsigned int addr, unsigned int count){ __raw_writel(0, REG_BASE_HOST + PCI_master_read_reverse); __raw_writel(addr, REG_BASE_HOST + PCI_master_read_addr); __raw_writel(count, REG_BASE_HOST + PCI_master_read_counter);}void em86xx_pcimaster_start_read(int start){ __raw_writel(start ? 1 : 0, REG_BASE_HOST + PCI_master_read_enable);}void em86xx_pcimaster_setup_write(unsigned int addr, unsigned int count){ __raw_writel(0, REG_BASE_HOST + PCI_master_read_reverse); __raw_writel(addr, REG_BASE_HOST + PCI_master_write_addr); __raw_writel(count, REG_BASE_HOST + PCI_master_write_counter);}void em86xx_pcimaster_start_write(int start){ __raw_writel(start ? 1 : 0, REG_BASE_HOST + PCI_master_write_enable);}//// GPIO//int em86xx_gpio_read(int gpio){ return (__raw_readl(REG_BASE_SYSTEM + SYS_gpio_data) >> gpio) & 1;}void em86xx_gpio_write(int gpio, int data){ __raw_writel(data ? GPIO_DATA_SET(gpio) : GPIO_DATA_CLEAR(gpio), REG_BASE_SYSTEM + SYS_gpio_data);}void em86xx_gpio_setdirection(int gpio, int dir){ __raw_writel(dir ? GPIO_DIR_OUTPUT(gpio) : GPIO_DIR_INPUT(gpio), REG_BASE_SYSTEM + SYS_gpio_dir);}//// Miscellaneous//unsigned int em86xx_random(void){ unsigned int sum; sum = __raw_readl(REG_BASE_SYSTEM + SYS_clk_cnt); sum = (sum << 8) | ((sum >> 24) & 0xff); sum += __raw_readl(REG_BASE_SYSTEM + SYS_xtal_in_cnt); sum = (sum << 8) | ((sum >> 24) & 0xff); sum += __raw_readl(REG_BASE_SYSTEM + SYS_rclk_out_cnt); sum = (sum << 8) | ((sum >> 24) & 0xff); sum += __raw_readl(REG_BASE_SYSTEM + SYS_sel_clk_cnt); return sum;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -