void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size) { unsigned long dst = (unsigned long)pdst; unsigned long src = (unsigned long)psrc; struct dma_register *dst_ch, *src_ch; early_shadow_stamp(); /* We assume that everything is 4 byte aligned, so include * a basic sanity check */ BUG_ON(dst % 4); BUG_ON(src % 4); BUG_ON(size % 4); src_ch = 0; /* Find an avalible memDMA channel */ while (1) { if (src_ch == (struct dma_register *)MDMA_S0_NEXT_DESC_PTR) { dst_ch = (struct dma_register *)MDMA_D1_NEXT_DESC_PTR; src_ch = (struct dma_register *)MDMA_S1_NEXT_DESC_PTR; } else { dst_ch = (struct dma_register *)MDMA_D0_NEXT_DESC_PTR; src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR; } if (!bfin_read16(&src_ch->cfg)) break; else if (bfin_read16(&dst_ch->irq_status) & DMA_DONE) { bfin_write16(&src_ch->cfg, 0); break; } } /* Force a sync in case a previous config reset on this channel * occurred. This is needed so subsequent writes to DMA registers * are not spuriously lost/corrupted. */ __builtin_bfin_ssync(); /* Destination */ bfin_write32(&dst_ch->start_addr, dst); bfin_write16(&dst_ch->x_count, size >> 2); bfin_write16(&dst_ch->x_modify, 1 << 2); bfin_write16(&dst_ch->irq_status, DMA_DONE | DMA_ERR); /* Source */ bfin_write32(&src_ch->start_addr, src); bfin_write16(&src_ch->x_count, size >> 2); bfin_write16(&src_ch->x_modify, 1 << 2); bfin_write16(&src_ch->irq_status, DMA_DONE | DMA_ERR); /* Enable */ bfin_write16(&src_ch->cfg, DMAEN | WDSIZE_32); bfin_write16(&dst_ch->cfg, WNR | DI_EN | DMAEN | WDSIZE_32); /* Since we are atomic now, don't use the workaround ssync */ __builtin_bfin_ssync(); }
int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { if (argc != 3) { show_usage: printf("Usage:\n%s\n", cmdtp->usage); return 1; } /* parse the behavior */ ulong port_cmd = 0; switch (argv[1][0]) { case 'i': break; case 's': port_cmd = (PORTFIO_SET - PORTFIO); break; case 'c': port_cmd = (PORTFIO_CLEAR - PORTFIO); break; case 't': port_cmd = (PORTFIO_TOGGLE - PORTFIO); break; default: goto show_usage; } /* parse the pin with format: [p]<fgh><#> */ const char *str_pin = argv[2]; /* grab the [p]<fgh> portion */ ulong port_base; if (*str_pin == 'p') ++str_pin; switch (*str_pin) { case 'f': port_base = PORTFIO; break; case 'g': port_base = PORTGIO; break; case 'h': port_base = PORTHIO; break; default: goto show_usage; } /* grab the <#> portion */ ulong pin = simple_strtoul(str_pin+1, NULL, 10); ulong pin_mask = (1 << pin); if (pin > 15) goto show_usage; /* finally, let's do it: set direction and exec command */ switch (*str_pin) { case 'f': bfin_write_PORTF_FER(bfin_read_PORTF_FER() & ~pin_mask); break; case 'g': bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ~pin_mask); break; case 'h': bfin_write_PORTH_FER(bfin_read_PORTH_FER() & ~pin_mask); break; } ulong port_dir = port_base + (PORTFIO_DIR - PORTFIO); if (argv[1][0] == 'i') bfin_write16(port_dir, bfin_read16(port_dir) & ~pin_mask); else { bfin_write16(port_dir, bfin_read16(port_dir) | pin_mask); bfin_write16(port_base + port_cmd, pin_mask); } printf("gpio: pin %li on port %c has been %c\n", pin, *str_pin, argv[1][0]); return 0; }
void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size) { unsigned long dst = (unsigned long)pdst; unsigned long src = (unsigned long)psrc; struct dma_register *dst_ch, *src_ch; early_shadow_stamp(); BUG_ON(dst % 4); BUG_ON(src % 4); BUG_ON(size % 4); src_ch = 0; while (1) { if (src_ch == (struct dma_register *)MDMA_S0_NEXT_DESC_PTR) { dst_ch = (struct dma_register *)MDMA_D1_NEXT_DESC_PTR; src_ch = (struct dma_register *)MDMA_S1_NEXT_DESC_PTR; } else { dst_ch = (struct dma_register *)MDMA_D0_NEXT_DESC_PTR; src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR; } if (!bfin_read16(&src_ch->cfg)) break; else if (bfin_read16(&dst_ch->irq_status) & DMA_DONE) { bfin_write16(&src_ch->cfg, 0); break; } } __builtin_bfin_ssync(); bfin_write32(&dst_ch->start_addr, dst); bfin_write16(&dst_ch->x_count, size >> 2); bfin_write16(&dst_ch->x_modify, 1 << 2); bfin_write16(&dst_ch->irq_status, DMA_DONE | DMA_ERR); bfin_write32(&src_ch->start_addr, src); bfin_write16(&src_ch->x_count, size >> 2); bfin_write16(&src_ch->x_modify, 1 << 2); bfin_write16(&src_ch->irq_status, DMA_DONE | DMA_ERR); bfin_write16(&src_ch->cfg, DMAEN | WDSIZE_32); bfin_write16(&dst_ch->cfg, WNR | DI_EN | DMAEN | WDSIZE_32); __builtin_bfin_ssync(); }
static irqreturn_t ppi_irq_err(int irq, void *dev_id) { struct ppi_if *ppi = dev_id; const struct ppi_info *info = ppi->info; switch (info->type) { case PPI_TYPE_PPI: { struct bfin_ppi_regs *reg = info->base; unsigned short status; /* register on bf561 is cleared when read * others are W1C */ status = bfin_read16(®->status); if (status & 0x3000) ppi->err = true; bfin_write16(®->status, 0xff00); break; } case PPI_TYPE_EPPI: { struct bfin_eppi_regs *reg = info->base; unsigned short status; status = bfin_read16(®->status); if (status & 0x2) ppi->err = true; bfin_write16(®->status, 0xffff); break; } case PPI_TYPE_EPPI3: { struct bfin_eppi3_regs *reg = info->base; unsigned long stat; stat = bfin_read32(®->stat); if (stat & 0x2) ppi->err = true; bfin_write32(®->stat, 0xc0ff); break; } default: break; } return IRQ_HANDLED; }
void get_bf537_ether_addr(char *addr) { unsigned int flash_mac = (unsigned int) FLASH_MAC; *(u32 *)(&(addr[0])) = bfin_read32(flash_mac); flash_mac += 4; *(u16 *)(&(addr[4])) = bfin_read16(flash_mac); }
static irqreturn_t ppi_irq_err(int irq, void *dev_id) { struct ppi_if *ppi = dev_id; const struct ppi_info *info = ppi->info; switch (info->type) { case PPI_TYPE_PPI: { struct bfin_ppi_regs *reg = info->base; unsigned short status; status = bfin_read16(®->status); bfin_write16(®->status, 0xff00); break; } case PPI_TYPE_EPPI: { struct bfin_eppi_regs *reg = info->base; bfin_write16(®->status, 0xffff); break; } default: break; } return IRQ_HANDLED; }
static int sport_get(void *mmr, u64 *val) { unsigned long flags; local_irq_save(flags); if (sport_width(mmr) <= 16) *val = bfin_read16(mmr); else *val = bfin_read32(mmr); local_irq_restore(flags); return 0; }
static inline int sport_width(void *mmr) { unsigned long lmmr = (unsigned long)mmr; if ((lmmr & 0xff) == 0x10) lmmr -= 0xc; else lmmr += 0xc; return (bfin_read16(lmmr) & 0x1f) + 1; }
int serial_getc(void) { uint16_t uart_rbr_val; /* wait for data ! */ while (!serial_tstc()) continue; /* grab the new byte */ uart_rbr_val = bfin_read16(&pUART->rbr); #ifdef CONFIG_DEBUG_SERIAL /* grab & clear the LSR */ uint16_t uart_lsr_val = uart_lsr_read(); cached_lsr[cache_count] = uart_lsr_val; cached_rbr[cache_count] = uart_rbr_val; cache_count = (cache_count + 1) % ARRAY_SIZE(cached_lsr); if (uart_lsr_val & (OE|PE|FE|BI)) { uint16_t dll, dlh; printf("\n[SERIAL ERROR]\n"); ACCESS_LATCH(); dll = bfin_read16(&pUART->dll); dlh = bfin_read16(&pUART->dlh); ACCESS_PORT_IER(); printf("\tDLL=0x%x DLH=0x%x\n", dll, dlh); do { --cache_count; printf("\t%3i: RBR=0x%02x LSR=0x%02x\n", cache_count, cached_rbr[cache_count], cached_lsr[cache_count]); } while (cache_count > 0); return -1; } #endif uart_lsr_clear(); return uart_rbr_val; }
static inline void serial_init(void) { #ifdef __ADSPBF54x__ # ifdef BFIN_BOOT_UART_USE_RTS # define BFIN_UART_USE_RTS 1 # else # define BFIN_UART_USE_RTS 0 # endif if (BFIN_UART_USE_RTS && CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { size_t i; /* force RTS rather than relying on auto RTS */ bfin_write16(&pUART->mcr, bfin_read16(&pUART->mcr) | FCPOL); /* Wait for the line to clear up. We cannot rely on UART * registers as none of them reflect the status of the RSR. * Instead, we'll sleep for ~10 bit times at 9600 baud. * We can precalc things here by assuming boot values for * PLL rather than loading registers and calculating. * baud = SCLK / (16 ^ (1 - EDBO) * Divisor) * EDB0 = 0 * Divisor = (SCLK / baud) / 16 * SCLK = baud * 16 * Divisor * SCLK = (0x14 * CONFIG_CLKIN_HZ) / 5 * CCLK = (16 * Divisor * 5) * (9600 / 10) * In reality, this will probably be just about 1 second delay, * so assuming 9600 baud is OK (both as a very low and too high * speed as this will buffer things enough). */ #define _NUMBITS (10) /* how many bits to delay */ #define _LOWBAUD (9600) /* low baud rate */ #define _SCLK ((0x14 * CONFIG_CLKIN_HZ) / 5) /* SCLK based on PLL */ #define _DIVISOR ((_SCLK / _LOWBAUD) / 16) /* UART DLL/DLH */ #define _NUMINS (3) /* how many instructions in loop */ #define _CCLK (((16 * _DIVISOR * 5) * (_LOWBAUD / _NUMBITS)) / _NUMINS) i = _CCLK; while (i--) asm volatile("" : : : "memory"); }
long probe_kernel_read(void *dst, const void *src, size_t size) { unsigned long lsrc = (unsigned long)src; int mem_type; mem_type = validate_memory_access_address(lsrc, size); if (mem_type < 0) return mem_type; if (lsrc >= SYSMMR_BASE) { if (size == 2 && lsrc % 2 == 0) { u16 mmr = bfin_read16(src); memcpy(dst, &mmr, sizeof(mmr)); return 0; } else if (size == 4 && lsrc % 4 == 0) { u32 mmr = bfin_read32(src); memcpy(dst, &mmr, sizeof(mmr)); return 0; } } else { switch (mem_type) { case BFIN_MEM_ACCESS_CORE: case BFIN_MEM_ACCESS_CORE_ONLY: return __probe_kernel_read(dst, src, size); case BFIN_MEM_ACCESS_DMA: if (dma_memcpy(dst, src, size)) return 0; break; case BFIN_MEM_ACCESS_ITEST: if (isram_memcpy(dst, src, size)) return 0; break; } } return -EFAULT; }
/* When debugging is disabled, we only care about the DR bit, so if other * bits get set/cleared, we don't really care since we don't read them * anyways (and thus anomaly 05000099 is irrelevant). */ static uint16_t uart_lsr_read(void) { return bfin_read16(&pUART->lsr); }
static uint16_t uart_lsr_read(void) { uint16_t lsr = bfin_read16(&pUART->lsr); uart_lsr_save |= (lsr & (OE|PE|FE|BI)); return lsr | uart_lsr_save; }
static int bfmdma_read_proc(char *buffer, char **start, off_t offset, int cnt, int *eof, void *data) { char *head = buffer; unsigned short s0_irqstat = bfin_read16(MDMA_S0_IRQ_STATUS); unsigned short d0_irqstat = bfin_read16(MDMA_D0_IRQ_STATUS); unsigned short s1_irqstat = bfin_read16(MDMA_S1_IRQ_STATUS); unsigned short d1_irqstat = bfin_read16(MDMA_D1_IRQ_STATUS); if (offset == 0) { head += sprintf(head, "MDMA Status\n"); head += sprintf(head, "S0: (RUN:%d DFETCH:%d ERR:%d DONE:%d)\n", (s0_irqstat >> 3) & 1, (s0_irqstat >> 2) & 1, (s0_irqstat >> 1) & 1, (s0_irqstat) & 1); head += sprintf(head, "(S0) CFG: %04x IRQ: %04x CUR: %08x NXT: %08x\n", bfin_read16(MDMA_S0_CONFIG), bfin_read16(MDMA_S0_IRQ_STATUS), bfin_read32(MDMA_S0_CURR_DESC_PTR), bfin_read32(MDMA_S0_NEXT_DESC_PTR)); head += sprintf(head, "SAH/L: %08x X(%d,+%d) Y(%d,+%d) current %08x cx: %d cy: %d\n", bfin_read32(MDMA_S0_START_ADDR), bfin_read16(MDMA_S0_X_COUNT), bfin_read16(MDMA_S0_X_MODIFY), bfin_read16(MDMA_S0_Y_COUNT), bfin_read16(MDMA_S0_Y_MODIFY), bfin_read32(MDMA_S0_CURR_ADDR), bfin_read16(MDMA_S0_CURR_X_COUNT), bfin_read16(MDMA_S0_CURR_Y_COUNT)); head += sprintf(head, "\n"); head += sprintf(head, "D0: (RUN:%d DFETCH:%d ERR:%d DONE:%d)\n", (d0_irqstat >> 3) & 1, (d0_irqstat >> 2) & 1, (d0_irqstat >> 1) & 1, (d0_irqstat) & 1); head += sprintf(head, "(D0) CFG: %04x IRQ: %04x CUR: %08x NXT: %08x\n", bfin_read16(MDMA_D0_CONFIG), bfin_read16(MDMA_D0_IRQ_STATUS), bfin_read32(MDMA_D0_CURR_DESC_PTR), bfin_read32(MDMA_D0_NEXT_DESC_PTR)); head += sprintf(head, "SAH/L: %08x X(%d,+%d) Y(%d,+%d) current %08x cx: %d cy: %d\n", bfin_read32(MDMA_D0_START_ADDR), bfin_read16(MDMA_D0_X_COUNT), bfin_read16(MDMA_D0_X_MODIFY), bfin_read16(MDMA_D0_Y_COUNT), bfin_read16(MDMA_D0_Y_MODIFY), bfin_read32(MDMA_D0_CURR_ADDR), bfin_read16(MDMA_D0_CURR_X_COUNT), bfin_read16(MDMA_D0_CURR_Y_COUNT)); head += sprintf(head, "\n"); head += sprintf(head, "S1: (RUN:%d DFETCH:%d ERR:%d DONE:%d)\n", (s1_irqstat >> 3) & 1, (s1_irqstat >> 2) & 1, (s1_irqstat >> 1) & 1, (s1_irqstat) & 1); head += sprintf(head, "(S1) CFG: %04x IRQ: %04x CUR: %08x NXT: %08x\n", bfin_read16(MDMA_S1_CONFIG), bfin_read16(MDMA_S1_IRQ_STATUS), bfin_read32(MDMA_S1_CURR_DESC_PTR), bfin_read32(MDMA_S1_NEXT_DESC_PTR)); head += sprintf(head, "SAH/L: %08x X(%d,+%d) Y(%d,+%d) current %08x cx: %d cy: %d\n", bfin_read32(MDMA_S1_START_ADDR), bfin_read16(MDMA_S1_X_COUNT), bfin_read16(MDMA_S1_X_MODIFY), bfin_read16(MDMA_S1_Y_COUNT), bfin_read16(MDMA_S1_Y_MODIFY), bfin_read32(MDMA_S1_CURR_ADDR), bfin_read16(MDMA_S1_CURR_X_COUNT), bfin_read16(MDMA_S1_CURR_Y_COUNT)); head += sprintf(head, "\n"); head += sprintf(head, "D1: (RUN:%d DFETCH:%d ERR:%d DONE:%d)\n", (d1_irqstat >> 3) & 1, (d1_irqstat >> 2) & 1, (d1_irqstat >> 1) & 1, (d1_irqstat) & 1); head += sprintf(head, "(D1) CFG: %04x IRQ: %04x CUR: %08x NXT: %08x\n", bfin_read16(MDMA_D1_CONFIG), bfin_read16(MDMA_D1_IRQ_STATUS), bfin_read32(MDMA_D1_CURR_DESC_PTR), bfin_read32(MDMA_D1_NEXT_DESC_PTR)); head += sprintf(head, "SAH/L: %08x X(%d,+%d) Y(%d,+%d) current %08x cx: %d cy: %d\n", bfin_read32(MDMA_D1_START_ADDR), bfin_read16(MDMA_D1_X_COUNT), bfin_read16(MDMA_D1_X_MODIFY), bfin_read16(MDMA_D1_Y_COUNT), bfin_read16(MDMA_D1_Y_MODIFY), bfin_read32(MDMA_D1_CURR_ADDR), bfin_read16(MDMA_D1_CURR_X_COUNT), bfin_read16(MDMA_D1_CURR_Y_COUNT)); }
int bfin_get_ether_addr(char *addr) { *(u32 *)(&(addr[0])) = bfin_read32(FLASH_MAC); *(u16 *)(&(addr[4])) = bfin_read16(FLASH_MAC + 4); return 0; }
void init_clocks(void) { /* Kill any active DMAs as they may trigger external memory accesses * in the middle of reprogramming things, and that'll screw us up. * For example, any automatic DMAs left by U-Boot for splash screens. */ size_t i; for (i = 0; i < MAX_DMA_CHANNELS; ++i) { struct dma_register *dma = dma_io_base_addr[i]; dma->cfg = 0; } do_sync(); #ifdef SIC_IWR0 bfin_write_SIC_IWR0(IWR_ENABLE(0)); # ifdef SIC_IWR1 /* BF52x system reset does not properly reset SIC_IWR1 which * will screw up the bootrom as it relies on MDMA0/1 waking it * up from IDLE instructions. See this report for more info: * http://blackfin.uclinux.org/gf/tracker/4323 */ if (ANOMALY_05000435) bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); else bfin_write_SIC_IWR1(IWR_DISABLE_ALL); # endif # ifdef SIC_IWR2 bfin_write_SIC_IWR2(IWR_DISABLE_ALL); # endif #else bfin_write_SIC_IWR(IWR_ENABLE(0)); #endif do_sync(); #ifdef EBIU_SDGCTL bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() | SRFS); do_sync(); #endif #ifdef CLKBUFOE bfin_write16(VR_CTL, bfin_read_VR_CTL() | CLKBUFOE); do_sync(); __asm__ __volatile__("IDLE;"); #endif bfin_write_PLL_LOCKCNT(0x300); do_sync(); bfin_write16(PLL_CTL, PLL_CTL_VAL); __asm__ __volatile__("IDLE;"); bfin_write_PLL_DIV(CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV); #ifdef EBIU_SDGCTL bfin_write_EBIU_SDRRC(mem_SDRRC); bfin_write_EBIU_SDGCTL((bfin_read_EBIU_SDGCTL() & SDGCTL_WIDTH) | mem_SDGCTL); #else bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() & ~(SRREQ)); do_sync(); bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | 0x1); bfin_write_EBIU_DDRCTL0(mem_DDRCTL0); bfin_write_EBIU_DDRCTL1(mem_DDRCTL1); bfin_write_EBIU_DDRCTL2(mem_DDRCTL2); #ifdef CONFIG_MEM_EBIU_DDRQUE bfin_write_EBIU_DDRQUE(CONFIG_MEM_EBIU_DDRQUE); #endif #endif do_sync(); bfin_read16(0); }
static void uart_lsr_clear(void) { bfin_write16(&pUART->lsr, bfin_read16(&pUART->lsr) | -1); }