📄 scc.c
字号:
static struct scc_dma_state scc_state_wr_39[] = { {0} };static struct scc_dma_state scc_state_rd_40[] = { {-1} };static struct scc_dma_state scc_state_wr_40[] = { {-1} };/* DMA state references to access from the driver */static struct scc_dma_state *scc_state_rd[] = { scc_state_rd_0, scc_state_rd_1, scc_state_rd_2, scc_state_rd_3, scc_state_rd_4, scc_state_rd_5, scc_state_rd_6, scc_state_rd_7, scc_state_rd_8, scc_state_rd_9, scc_state_rd_10, scc_state_rd_11, scc_state_rd_12, scc_state_rd_13, scc_state_rd_14, scc_state_rd_15, scc_state_rd_16, scc_state_rd_17, scc_state_rd_18, scc_state_rd_19, scc_state_rd_20, scc_state_rd_21, scc_state_rd_22, scc_state_rd_23, scc_state_rd_24, scc_state_rd_25, scc_state_rd_26, scc_state_rd_27, scc_state_rd_28, scc_state_rd_29, scc_state_rd_30, scc_state_rd_31, scc_state_rd_32, scc_state_rd_33, scc_state_rd_34, scc_state_rd_35, scc_state_rd_36, scc_state_rd_37, scc_state_rd_38, scc_state_rd_39, scc_state_rd_40,};static struct scc_dma_state *scc_state_wr[] = { scc_state_wr_0, scc_state_wr_1, scc_state_wr_2, scc_state_wr_3, scc_state_wr_4, scc_state_wr_5, scc_state_wr_6, scc_state_wr_7, scc_state_wr_8, scc_state_wr_9, scc_state_wr_10, scc_state_wr_11, scc_state_wr_12, scc_state_wr_13, scc_state_wr_14, scc_state_wr_15, scc_state_wr_16, scc_state_wr_17, scc_state_wr_18, scc_state_wr_19, scc_state_wr_20, scc_state_wr_21, scc_state_wr_22, scc_state_wr_23, scc_state_wr_24, scc_state_wr_25, scc_state_wr_26, scc_state_wr_27, scc_state_wr_28, scc_state_wr_29, scc_state_wr_30, scc_state_wr_31, scc_state_wr_32, scc_state_wr_33, scc_state_wr_34, scc_state_wr_35, scc_state_wr_36, scc_state_wr_37, scc_state_wr_38, scc_state_wr_39, scc_state_wr_40,};static u32 scc_takeover_mode = SCC_TO_IMMEDIATE;/* Change mode of the SPDMA for given direction */static u32 scc_agu_mode_sp = AGU_BYPASS;/* Change mode of the USB for given direction */static u32 scc_agu_mode_usb = AGU_BYPASS;static union scc_softwareconfiguration scc_software_configuration[SCC_MAX];static u32 dma_fsm[4][4] = { /* DMA_CMD_RESET DMA_CMD_SETUP DMA_CMD_START DMA_CMD_STOP */ /* DMA_STATE_RESET */ {DMA_STATE_RESET, DMA_STATE_SETUP, DMA_STATE_ERROR, DMA_STATE_ERROR}, /* DMA_STATE_SETUP */ {DMA_STATE_RESET, DMA_STATE_SETUP, DMA_STATE_START, DMA_STATE_SETUP}, /* DMA_STATE_START */ {DMA_STATE_RESET, DMA_STATE_ERROR, DMA_STATE_START, DMA_STATE_SETUP}, /* DMA_STATE_ERROR */ {DMA_STATE_RESET, DMA_STATE_ERROR, DMA_STATE_ERROR, DMA_STATE_ERROR},};static void dma_state_process(struct scc_dma_state *dma_state, u32 cmd){ dma_state->dma_status = dma_fsm[dma_state->dma_status][cmd]; dma_state->dma_cmd = cmd;}static void dma_state_process_dma_command(struct scc_dma_state *dma_state, u32 dma_cmd){ dma_state->dma_cmd = dma_cmd; switch (dma_cmd) { case DMA_START: case DMA_START_FH_RESET: dma_state_process(dma_state, DMA_CMD_START); break; case DMA_STOP: dma_state_process(dma_state, DMA_CMD_STOP); break; default: break; }}static void scc_takeover_dma(enum scc_id id, u32 dma_id, u32 drs){ union scc_cmd dma_cmd; dma_cmd.reg = 0; /* Prepare the takeover for the DMA channel */ dma_cmd.bits.action = DMA_TAKEOVER; dma_cmd.bits.id = dma_id; dma_cmd.bits.rid = TO_DMA_CFG; /* this is DMA_CFG register takeover */ if (drs == DMA_WRITE) dma_cmd.bits.drs = DMA_WRITE; reg_write(SCC_CMD(scc_descriptor_table[id].base_address), dma_cmd.reg);}int scc_dma_cmd(enum scc_id id, u32 cmd, u32 dma_id, u32 drs){ union scc_cmd dma_cmd; struct scc_dma_state *dma_state; if ((id >= SCC_MAX) || (id < 0)) return -EINVAL; dma_cmd.reg = 0; /* Prepare the takeover for the DMA channel */ dma_cmd.bits.action = cmd; dma_cmd.bits.id = dma_id; if (drs == DMA_WRITE) { dma_cmd.bits.drs = DMA_WRITE; dma_state = &scc_state_wr[id][dma_id]; } else { dma_state = &scc_state_rd[id][dma_id]; } dma_state->scc_id = id; dma_state->dma_id = dma_id; dma_state_process_dma_command(dma_state, cmd); reg_write(SCC_CMD(scc_descriptor_table[id].base_address), dma_cmd.reg); return 0;}int scc_set_usb_address_generation_mode(u32 agu_mode){ if (AGU_ACTIVE == agu_mode) { /* Ensure both DMAs are stopped */ scc_dma_cmd(SCC_USB_RW, DMA_STOP, 0, DMA_WRITE); scc_dma_cmd(SCC_USB_RW, DMA_STOP, 0, DMA_READ); } else { agu_mode = AGU_BYPASS; } scc_agu_mode_usb = agu_mode; return 0;}int scc_setup_dma(enum scc_id id, u32 buffer_tag, u32 type, u32 fh_mode, u32 drs, u32 dma_id){ struct scc_dma_state *dma_state; int return_value = 0; union scc_dma_cfg dma_cfg; u32 *buffer_tag_list = scc_descriptor_table[id].buffer_tag_list; u32 tag_count, t, t_valid; if ((id >= SCC_MAX) || (id < 0)) return -EINVAL; /* if the register is only configured by hw, cannot write! */ if (1 == scc_descriptor_table[id].hw_dma_cfg) return -EACCES; if (DMA_WRITE == drs) { if (dma_id >= scc_descriptor_table[id].p_dma_channels_wr) return -EINVAL; dma_state = &scc_state_wr[id][dma_id]; } else { if (dma_id >= scc_descriptor_table[id].p_dma_channels_rd) return -EINVAL; dma_state = &scc_state_rd[id][dma_id]; } /* Compose the DMA configuration register */ tag_count = buffer_tag_list[0]; t_valid = 0; for (t = 1; t <= tag_count; t++) { if (buffer_tag == buffer_tag_list[t]) { /* Tag found - validate */ t_valid = 1; break; } } if (!t_valid) return -EACCES; /* * Read the register first -- two functions write into the register * it does not make sense to read the DMA config back, because there * are two register configuration sets (drs) */ dma_cfg.reg = 0; dma_cfg.bits.buffer_id = buffer_tag; dma_state_process(dma_state, DMA_CMD_SETUP); /* * This is Packet CFG set select - usable for TSIO, EBI and those SCCs * which habe 2 packet configs */ dma_cfg.bits.packet_cfg_id = scc_software_configuration[id].bits.packet_select; if (type == DMA_CYCLIC) dma_cfg.bits.buffer_type = 1; else dma_cfg.bits.buffer_type = 0; if (fh_mode == USE_FH) dma_cfg.bits.fh_mode = 1; else dma_cfg.bits.fh_mode = 0; if (id == SCC_CPU1_SPDMA_RW) dma_cfg.bits.agu_mode = scc_agu_mode_sp; if (id == SCC_USB_RW) dma_cfg.bits.agu_mode = scc_agu_mode_usb; reg_write(SCC_DMA_CFG(scc_descriptor_table[id].base_address), dma_cfg.reg); /* The DMA_CFG needs a takeover! */ if (SCC_TO_IMMEDIATE == scc_takeover_mode) scc_takeover_dma(id, dma_id, drs); /* if (buffer_tag is not used) */ dma_state->buffer_tag = buffer_tag; dma_state->scc_id = id; dma_state->dma_id = dma_id; return return_value;}int scc_enable(enum scc_id id, u32 value){ if ((id >= SCC_MAX) || (id < 0)) return -EINVAL; if (value == 0) { scc_software_configuration[id].bits.enable_status = 0; } else { value = 1; scc_software_configuration[id].bits.enable_status = 1; } reg_write(SCC_ENABLE(scc_descriptor_table[id].base_address), value); return 0;}static inline void ehb(void){ __asm__ __volatile__( " .set mips32r2 \n" " ehb \n" " .set mips0 \n");}int scc_reset(enum scc_id id, u32 value){ if ((id >= SCC_MAX) || (id < 0)) return -EINVAL; /* Invert value to the strait logic from the negative hardware logic */ if (value == 0) value = 1; else value = 0; /* Write the value to the register */ reg_write(SCC_RESET(scc_descriptor_table[id].base_address), value); /* sync flush */ asm("sync"); /* request bus write queue flush */ ehb(); /* wait until previous bus commit instr has finished */ asm("nop"); /* wait for flush to occur */ asm("nop"); /* wait for flush to occur */ udelay(100); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -