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; }
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; }
static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) { const struct ppi_info *info = ppi->info; int dma32 = 0; int dma_config, bytes_per_line, lines_per_frame; bytes_per_line = params->width * params->bpp / 8; lines_per_frame = params->height; if (params->int_mask == 0xFFFFFFFF) ppi->err_int = false; else ppi->err_int = true; dma_config = (DMA_FLOW_STOP | WNR | RESTART | DMA2D | DI_EN); ppi->ppi_control = params->ppi_control & ~PORT_EN; switch (info->type) { case PPI_TYPE_PPI: { struct bfin_ppi_regs *reg = info->base; if (params->ppi_control & DMA32) dma32 = 1; bfin_write16(®->control, ppi->ppi_control); bfin_write16(®->count, bytes_per_line - 1); bfin_write16(®->frame, lines_per_frame); break; } case PPI_TYPE_EPPI: { struct bfin_eppi_regs *reg = info->base; if ((params->ppi_control & PACK_EN) || (params->ppi_control & 0x38000) > DLEN_16) dma32 = 1; bfin_write32(®->control, ppi->ppi_control); bfin_write16(®->line, bytes_per_line + params->blank_clocks); bfin_write16(®->frame, lines_per_frame); bfin_write16(®->hdelay, 0); bfin_write16(®->vdelay, 0); bfin_write16(®->hcount, bytes_per_line); bfin_write16(®->vcount, lines_per_frame); break; } default: return -EINVAL; } if (dma32) { dma_config |= WDSIZE_32; set_dma_x_count(info->dma_ch, bytes_per_line >> 2); set_dma_x_modify(info->dma_ch, 4); set_dma_y_modify(info->dma_ch, 4); } else {
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; }
static int ppi_start(struct ppi_if *ppi) { const struct ppi_info *info = ppi->info; /* enable DMA */ enable_dma(info->dma_ch); /* enable PPI */ ppi->ppi_control |= PORT_EN; switch (info->type) { case PPI_TYPE_PPI: { struct bfin_ppi_regs *reg = info->base; bfin_write16(®->control, ppi->ppi_control); break; } case PPI_TYPE_EPPI: { struct bfin_eppi_regs *reg = info->base; bfin_write32(®->control, ppi->ppi_control); break; } case PPI_TYPE_EPPI3: { struct bfin_eppi3_regs *reg = info->base; bfin_write32(®->ctl, ppi->ppi_control); break; } default: return -EINVAL; } SSYNC(); return 0; }
static int ppi_stop(struct ppi_if *ppi) { const struct ppi_info *info = ppi->info; ppi->ppi_control &= ~PORT_EN; switch (info->type) { case PPI_TYPE_PPI: { struct bfin_ppi_regs *reg = info->base; bfin_write16(®->control, ppi->ppi_control); break; } case PPI_TYPE_EPPI: { struct bfin_eppi_regs *reg = info->base; bfin_write32(®->control, ppi->ppi_control); break; } default: return -EINVAL; } clear_dma_irqstat(info->dma_ch); disable_dma(info->dma_ch); SSYNC(); 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(); /* 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(); }
static int sport_set(void *mmr, u64 val) { unsigned long flags; local_irq_save(flags); if (sport_width(mmr) <= 16) bfin_write16(mmr, val); else bfin_write32(mmr, val); local_irq_restore(flags); return 0; }
/* * This function read or write data to endpoint fifo * Blackfin use DMA polling method to avoid buffer alignment issues * * ep - Endpoint number * length - Number of bytes to write to FIFO * fifo_data - Pointer to data buffer to be read/write * is_write - Flag for read or write */ void rw_fifo(u8 ep, u32 length, void *fifo_data, int is_write) { struct bfin_musb_dma_regs *regs; u32 val = (u32)fifo_data; blackfin_dcache_flush_invalidate_range(fifo_data, fifo_data + length); regs = (void *)USB_DMA_INTERRUPT; regs += ep; /* Setup DMA address register */ bfin_write16(®s->addr_low, val); SSYNC(); bfin_write16(®s->addr_high, val >> 16); SSYNC(); /* Setup DMA count register */ bfin_write16(®s->count_low, length); bfin_write16(®s->count_high, 0); SSYNC(); /* Enable the DMA */ val = (ep << 4) | DMA_ENA | INT_ENA; if (is_write) val |= DIRECTION; bfin_write16(®s->control, val); SSYNC(); /* Wait for compelete */ while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << ep))) continue; /* acknowledge dma interrupt */ bfin_write_USB_DMA_INTERRUPT(1 << ep); SSYNC(); /* Reset DMA */ bfin_write16(®s->control, 0); SSYNC(); }
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(); }
void serial_putc(const char c) { /* send a \r for compatibility */ if (c == '\n') serial_putc('\r'); WATCHDOG_RESET(); /* wait for the hardware fifo to clear up */ while (!(uart_lsr_read() & THRE)) continue; /* queue the character for transmission */ bfin_write16(&pUART->thr, c); SSYNC(); WATCHDOG_RESET(); }
long probe_kernel_write(void *dst, const void *src, size_t size) { unsigned long ldst = (unsigned long)dst; int mem_type; mem_type = validate_memory_access_address(ldst, size); if (mem_type < 0) return mem_type; if (ldst >= SYSMMR_BASE) { if (size == 2 && ldst % 2 == 0) { u16 mmr; memcpy(&mmr, src, sizeof(mmr)); bfin_write16(dst, mmr); return 0; } else if (size == 4 && ldst % 4 == 0) { u32 mmr; memcpy(&mmr, src, sizeof(mmr)); bfin_write32(dst, mmr); return 0; } } else { switch (mem_type) { case BFIN_MEM_ACCESS_CORE: case BFIN_MEM_ACCESS_CORE_ONLY: return __probe_kernel_write(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; }
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"); }
static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) { const struct ppi_info *info = ppi->info; int dma32 = 0; int dma_config, bytes_per_line; int hcount, hdelay, samples_per_line; bytes_per_line = params->width * params->bpp / 8; /* convert parameters unit from pixels to samples */ hcount = params->width * params->bpp / params->dlen; hdelay = params->hdelay * params->bpp / params->dlen; samples_per_line = params->line * params->bpp / params->dlen; if (params->int_mask == 0xFFFFFFFF) ppi->err_int = false; else ppi->err_int = true; dma_config = (DMA_FLOW_STOP | RESTART | DMA2D | DI_EN_Y); ppi->ppi_control = params->ppi_control & ~PORT_EN; if (!(ppi->ppi_control & PORT_DIR)) dma_config |= WNR; switch (info->type) { case PPI_TYPE_PPI: { struct bfin_ppi_regs *reg = info->base; if (params->ppi_control & DMA32) dma32 = 1; bfin_write16(®->control, ppi->ppi_control); bfin_write16(®->count, samples_per_line - 1); bfin_write16(®->frame, params->frame); break; } case PPI_TYPE_EPPI: { struct bfin_eppi_regs *reg = info->base; if ((params->ppi_control & PACK_EN) || (params->ppi_control & 0x38000) > DLEN_16) dma32 = 1; bfin_write32(®->control, ppi->ppi_control); bfin_write16(®->line, samples_per_line); bfin_write16(®->frame, params->frame); bfin_write16(®->hdelay, hdelay); bfin_write16(®->vdelay, params->vdelay); bfin_write16(®->hcount, hcount); bfin_write16(®->vcount, params->height); break; } case PPI_TYPE_EPPI3: { struct bfin_eppi3_regs *reg = info->base; if ((params->ppi_control & PACK_EN) || (params->ppi_control & 0x70000) > DLEN_16) dma32 = 1; bfin_write32(®->ctl, ppi->ppi_control); bfin_write32(®->line, samples_per_line); bfin_write32(®->frame, params->frame); bfin_write32(®->hdly, hdelay); bfin_write32(®->vdly, params->vdelay); bfin_write32(®->hcnt, hcount); bfin_write32(®->vcnt, params->height); if (params->int_mask) bfin_write32(®->imsk, params->int_mask & 0xFF); break; } default: return -EINVAL; } if (dma32) { dma_config |= WDSIZE_32 | PSIZE_32; set_dma_x_count(info->dma_ch, bytes_per_line >> 2); set_dma_x_modify(info->dma_ch, 4); set_dma_y_modify(info->dma_ch, 4); } else {
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); }