/* Run the BDC controller */ int bdc_run(struct bdc *bdc)
{
u32 temp; int ret;
dev_dbg(bdc->dev, "%s ()\n", __func__);
temp = bdc_readl(bdc->regs, BDC_BDCSC); /* if BDC is already in running state then do not do anything */ if (BDC_CSTS(temp) == BDC_NOR) {
dev_warn(bdc->dev, "bdc is already in running state\n"); return 0;
}
temp &= ~BDC_COP_MASK;
temp |= BDC_COP_RUN;
temp |= BDC_COS;
bdc_writel(bdc->regs, BDC_BDCSC, temp);
ret = poll_oip(bdc, BDC_COP_TIMEOUT); if (ret) {
dev_err(bdc->dev, "bdc run operation failed:%d", ret); return ret;
}
temp = bdc_readl(bdc->regs, BDC_BDCSC); if (BDC_CSTS(temp) != BDC_NOR) {
dev_err(bdc->dev, "bdc not in normal mode after RUN op :%d\n",
BDC_CSTS(temp)); return -ESHUTDOWN;
}
return 0;
}
/* * Present the termination to the host, typically called from upstream port * event with Vbus present =1
*/ void bdc_softconn(struct bdc *bdc)
{
u32 uspc;
/* Set up the scratchpad buffer array and scratchpad buffers, if needed. */ staticint scratchpad_setup(struct bdc *bdc)
{ int sp_buff_size;
u32 low32;
u32 upp32;
sp_buff_size = BDC_SPB(bdc_readl(bdc->regs, BDC_BDCCFG0));
dev_dbg(bdc->dev, "%s() sp_buff_size=%d\n", __func__, sp_buff_size); if (!sp_buff_size) {
dev_dbg(bdc->dev, "Scratchpad buffer not needed\n"); return 0;
} /* Refer to BDC spec, Table 4 for description of SPB */
sp_buff_size = 1 << (sp_buff_size + 5);
dev_dbg(bdc->dev, "Allocating %d bytes for scratchpad\n", sp_buff_size);
bdc->scratchpad.buff = dma_alloc_coherent(bdc->dev, sp_buff_size,
&bdc->scratchpad.sp_dma,
GFP_KERNEL);
/* Disable any unwanted SR's on SRR */
temp = bdc_readl(bdc->regs, BDC_BDCSC); /* We don't want Microframe counter wrap SR */
temp |= BDC_MASK_MCW;
bdc_writel(bdc->regs, BDC_BDCSC, temp);
/* * In some error cases, driver has to reset the entire BDC controller * in that case reinit is passed as 1
*/ if (reinit) { int i; /* Enable interrupts */
temp = bdc_readl(bdc->regs, BDC_BDCSC);
temp |= BDC_GIE;
bdc_writel(bdc->regs, BDC_BDCSC, temp); /* Init scratchpad to 0 */
memset(bdc->scratchpad.buff, 0, bdc->sp_buff_size); /* Initialize SRR to 0 */
memset(bdc->srr.sr_bds, 0,
NUM_SR_ENTRIES * sizeof(struct bdc_bd)); /* * clear ep flags to avoid post disconnect stops/deconfigs but * not during S2 exit
*/ if (!bdc->gadget.speed) for (i = 1; i < bdc->num_eps; ++i)
bdc->bdc_ep_array[i]->flags = 0;
} else { /* One time initiaization only */ /* Enable status report function pointers */
bdc->sr_handler[0] = bdc_sr_xsf;
bdc->sr_handler[1] = bdc_sr_uspc;
/* EP0 status report function pointers */
bdc->sr_xsf_ep0[0] = bdc_xsf_ep0_setup_recv;
bdc->sr_xsf_ep0[1] = bdc_xsf_ep0_data_start;
bdc->sr_xsf_ep0[2] = bdc_xsf_ep0_status_start;
}
}
/* * bdc reinit gives a controller reset and reinitialize the registers, * called from disconnect/bus reset scenario's, to ensure proper HW cleanup
*/ int bdc_reinit(struct bdc *bdc)
{ int ret;
dev_dbg(bdc->dev, "%s\n", __func__);
ret = bdc_stop(bdc); if (ret) goto out;
ret = bdc_reset(bdc); if (ret) goto out;
/* the reinit flag is 1 */
bdc_mem_init(bdc, true);
ret = bdc_run(bdc);
out:
bdc->reinit = false;
return ret;
}
/* Allocate all the dyanmic memory */ staticint bdc_mem_alloc(struct bdc *bdc)
{
u32 page_size; unsignedint num_ieps, num_oeps;
ret = clk_prepare_enable(bdc->clk); if (ret) {
dev_err(bdc->dev, "err enabling the clock\n"); return ret;
}
ret = bdc_reinit(bdc); if (ret) {
dev_err(bdc->dev, "err in bdc reinit\n");
clk_disable_unprepare(bdc->clk); return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.