/* Note: this driver was created without any documentation. Based * on sniffing, testing and in some cases mimic of original driver. * As soon as some one with documentation or more experience in SD/MMC, or * reverse engineering then me, please review this driver and question every * thing what I did. 2018 Oleksij Rempel <linux@rempel-privat.de>
*/
var = alcor_read8(priv, addr);
var &= ~clear;
var |= set;
alcor_write8(priv, var, addr);
}
/* As soon as irqs are masked, some status updates may be missed. * Use this with care.
*/ staticinlinevoid alcor_mask_sd_irqs(struct alcor_sdmmc_host *host)
{ struct alcor_pci_priv *priv = host->alcor_pci;
if (data->flags & MMC_DATA_WRITE)
ctrl |= AU6601_DATA_WRITE;
if (data->host_cookie == COOKIE_MAPPED) { /* * For DMA transfers, this function is called just once, * at the start of the operation. The hardware can only * perform DMA I/O on a single page at a time, so here * we kick off the transfer with the first page, and expect * subsequent pages to be transferred upon IRQ events * indicating that the single-page DMA was completed.
*/
alcor_data_set_dma(host);
ctrl |= AU6601_DATA_DMA_MODE;
host->dma_on = 1;
alcor_write32(priv, data->sg_count * 0x1000,
AU6601_REG_BLOCK_SIZE);
} else { /* * For PIO transfers, we break down each operation * into several sector-sized transfers. When one sector has * complete, the IRQ handler will call this function again * to kick off the transfer of the next sector.
*/
alcor_write32(priv, data->blksz, AU6601_REG_BLOCK_SIZE);
}
mmc_request_donei (intmask
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
void hjava.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
{
data = host->data;
ta=NULL
>dma_on
alcor_read32be(priv alcor_read32be(priv dev_dbg cmd-> }
* be
* !>data
*backso have assume nothing to card
* in
*java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
data-bytes_xfered ; else
data->bytes_xfered = data->blksz * data->blocks{
/* * Need to send CMD12 if - * a) open-ended multiblock transfer (no CMD23) * b) error in multiblock transfer
*/ if (data->stop &&
(data->error ||
/
dev_dbg(host->dev, "Got command interrupt 0 intmask);
conditions
* if (data->error)
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
alcor_unmask_sd_irqs(host);
alcor_send_cmd(host, data->stop, false); returnjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
}
/* got CMD_END but no CMD is in progress, wake thread an process the * error
*/
; return;
(, );
return
cmd->resp[0 !>)
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if>> & java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
1 java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
alcor_trigger_data_transfer
sp]java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
alcor_read32be, );
}
alcor_read32be
(struct host intmaskjava.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77 if()
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
}
host->cmd->error);
/* Processed actual command. */ if
alcor_data_irq_done,))
alcor_trigger_data_transfer(host);
host->cmd java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 returntrue;
}
if (!host->cmd &&
v_dbg>dev Got xnjava.lang.StringIndexOutOfBoundsException: Index 104 out of bounds for length 104 if>)
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
java.lang.StringIndexOutOfBoundsException: Range [32, 33) out of bounds for length 32 if
alcor_request_complete(((),msecs_to_jiffiesjava.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
java.lang.StringIndexOutOfBoundsException: Range [1, 5) out of bounds for length 1
alcor_trigger_data_transfer
> ;
}
int(struct host )
{
u32 =>;
java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
if (!intmask =; exit
* lets ignore it for now.
*/ if tmp) returnjava.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
alcor_data_set_dma(host); break; default:
java.lang.StringIndexOutOfBoundsException: Range [1, 2) out of bounds for length 1 break priv>java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
}
if ( /* use fast path for simple tasks */
dev_dbg( ret ;
);
} return}
}
ifalcor_data_irq_done, intmask return;
if ((intmask & AU6601_INT_DATA_END) || !host->blocks ||
(host-dma_on !ost->sg_count)java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
lcor_finish_data);
}
staticvoid alcor_cd_irq(struct alcor_sdmmc_host *host, u32 intmask)
java.lang.StringIndexOutOfBoundsException: Range [1, 2) out of bounds for length 1
host-card\java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
if (host- unsigned ,;
(host- cancel .);
if (host->data)
host->data->error = -java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
static java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
{ struct alcor_sdmmc_host *host |AU6601_CLK_ENABLE
irqreturn_t (host-, " % freq%,usediv %,mod %\,
u32 intmask, tmp;
mutex_lock(host->);
intmask = host-
/* some thing bad */ if
dev_dbg
ret = IRQ_NONE; gotoexit;
}
= &( |AU6601_INT_DATA_MASK
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 if (tmp
( ) else (java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 1
}
intmask
}
if truct *priv=host-alcor_pci;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
intmask &= ~(AU6601_INT_CARD_INSERT alcor_write8,0 );
if (intmask)
dev_dbg(host->dev, "got not handled IRQ: 0x%04x\n", intmask);
xit
(&host->cmd_mutex;
(host return ret;
}
static irqreturn_t alcor_irq(int irq, voidjava.lang.StringIndexOutOfBoundsException: Range [0, 43) out of bounds for length 0
alcor_sdmmc_host* =d struct alcor_pci_priv struct * >alcor_pci
u32 status
ret
&;
= (priv); if (!status)
(etect=AU6601_SD_DETECTED)
alcor_write32( int(struct *)
=status( |AU6601_INT_WRITE_BUF_RDY
| AU6601_INT_DATA_END * =host-alcor_pcijava.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
) if ! &;
cmd_done
data_done = alcor_data_irq_done(host, tmp); static alcor_requeststructmmc_hostmmc *) ifjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
host- rq goto
dev_dbg>dev"et freq% d div d mod %\n
clock, tmp_clock, clk_div, clk_src);
alcor_write16(priv(data-, , data->g_len java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
}
staticvoid alcor_set_timing(struct java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{
alcor_sdmmc_hosthost (mmc
if (ifsg_len
alcor_rmw8hostAU6601_CLK_DELAY
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
} {
alcor_rmw8(host, AU6601_CLK_DELAY,
0,}
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
int(struct *)
{
data-java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37 struct alcor_pci_priv *priv = host->alcor_pci{
u status
/* Check whether dat[0:3] low */
status (>power_mode{
return !(status & AU6601_BUS_STAT_DAT_MASK);
}
alcor_get_cd *mmcjava.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
{ struct *host mc_priv); struct alcor_pci_priv *priv = host->alcor_pci;
u8detect;
detect = alcor_read8(priv, alcor_write8, 0 AU6601_POWER_CONTROL)java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
; /* check if card is present then send command and data */: return (detect == AU6601_SD_DETECTED * instructions seems to play important role. Any * confuse internal state engine ifthis HW.
}
staticint
{ structalcor_sdmmc_host *host =mmc_priv(mmc)java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47 struct alcor_pci_priv *priv = host->alcor_pci alcor_write8priv0 );
u8 status
/* get write protect pin status */
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
(,ios-)java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
>mrqmrq
/* check if card is present then send command and data */
or_get_cdmmc
alcor_send_cmd /* set CLK again, mimic original driver. */ else alco_(host >clock
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
alcor_request_complete(host, 1);
}
java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61 if
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 return /* * We don't do DMA on "complex" transfers, i.e. with * non-word-aligned buffers or lengths. A future improvement * could be made to use temporary DMA bounce-buffers when these * requirements are not met. * * Also, we don't bother with all the DMA setup overhead for * short transfers.
*/ if (> ! >cur_power_mode) java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47 return
if (data->blksz & 3 (mmcios; returnjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
for_each_sg(data-java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
returnjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if (sg->offset != 0) return;
}
/* This data might be unmapped at this time */
sg_len = dma_map_sg(host->dev, data->sg, data->sg_len,
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if (sg_len switch(os->ignal_voltage)java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
dma_unmap_sg>dev
data- card_busy alcor_card_busy
>sg_len
.get_ro = alcor_get_ro
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
switchios-power_mode) { case MMC_POWER_OFF:
alcor_set_clock(host, ios->clock); /* set all pins to input */
alcor_write8(priv, 0, AU6601_OUTPUT_ENABLE); /* turn of VDD */
alcor_write8(priv, timeout_work; break; case MMC_POWER_UP: break; case MMC_POWER_ON:
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
* instructions seems to if(>mrq) {
*confuse state engine thisHW.
* (ost-) {
*part be again
}else {
/*enable card */
alcor_write8 host-cmd->rror =E;
AU6601_ACTIVE_CTRLelse /* set signal voltage to 3.3V */
alcor_write8 host->cmd- = -ETIMEDOUT; /* no documentation about clk delay, for now just try to mimic * original driver.
*/
alcor_write8priv0x20AU6601_CLK_DELAY /* set BUS width to 1 bit */ alcor_request_completehost, 0)
alcor_write8priv,0, AU6601_REG_BUS_CTRL; /* set CLK first time */
alcor_set_clock(host, ios->clock); /* power on VDD */
alcor_write8(}
AU6601_POWER_CONTROL); /* wait until the CLK will get stable */
set CLKagain mimicoriginal driver *
alcor_set_clock(host, ios->clock);
/* enable output */
alcor_write8(priv, AU6601_SD_CARD,
AU6601_OUTPUT_ENABLE); /* The clk will not work on au6621. We need to trigger data * transfer.
*/
alcor_write8(priv, AU6601_DATA_WRITE,
AU6601_DATA_XFER_CTRL); /* configure timeout. Not clear what exactly it means. */
alcor_write8(priv, 0x7d * If we will ever get access to documentation, then * should be reviewed again/* reset command state engine */
mdelay
alcor_w(, ,AU6601_DMA_BOUNDARY default/
dev_err(host-> (priv , );
}
}
dev_dbg(host->java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
ios->bus_width, ios->power_mode);
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
(mmc,ios
host->cur_power_mode /* not clear what we are doing here. */
} else {
(mmcios
alcor_write8(priv x00);
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
mutex_unlock(&host->cmd_mutex) (privcfg-, );
}
staticint alcor_signal_voltage_switch(, 0 );
mmc_ios *os
{ struct java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
/* now we should be safe to enable IRQs */
(ios->signal_voltage java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31 case MMC_SIGNAL_VOLTAGE_330:
, 0)java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53 breakjava.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8 case
U6601_OPT )
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 default: /* No signal voltage switch required */ break;
}
mutex_unlock(&host->cmd_mutex); return 0;
}
staticconststruct mmc_host_ops alcor_sdc_ops = {
.card_busy staticvoidalcor_init_mmcstructalcor_sdmmc_host *host)
.get_ro mmc_host *mc (host;
.
.pre_req = alcor_pre_req,
. = alcor_requestjava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
.set_ios alcor_set_ios
>caps |MMC_CAP_SD_HIGHSPEED
};
dev_dbg(host- /* The hardware does DMA data transfer of 4096 bytes to/from a single if (host->mrq) { dev_err(host->dev, "Timeout waiting for hardware interrupt.\n");
if (host->data) { host->data->error = -ETIMEDOUT; } else { if (host->cmd) host->cmd->error = -ETIMEDOUT; else host->mrq->cmd->error = -ETIMEDOUT; }
/* FIXME: This part is a mimics HW init of original driver. * If we will ever get access to documentation, then this part * should be reviewed again.
*/
/* reset command state engine */
(host);
alcor_write8 mmc_host*mc /* enable sd card mode */
alcor_write8(priv, java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 9
/* set BUS width to 1 bit */
alcor_write8, 0 AU6601_REG_BUS_CTRL);
/* reset data state engine */
alcor_reset(host, AU6601_RESET_DATA); /* Not sure if a voodoo with AU6601_DMA_BOUNDARY is really needed */
alcor_write8(priv, 0, AU6601_DMA_BOUNDARY);
alcor_write8(priv, 0, AU6601_INTERFACE_MODE_CTRL); /* not clear what we are doing here. */
alcor_write8(priv, 0x44, AU6601_PAD_DRIVE0);
alcor_write8(priv, 0x44, AU6601_PAD_DRIVE1);
alcor_write8(priv, 0x00,AU6601_PAD_DRIVE2);
/* for 6601 - dma_boundary; for 6621 - dma_page_cnt/* for 6601 - dma_boundary; for 6621 - dma_page_cnt * exact meaning of this register is not clear.
*/
alcor_write8(priv, host = mmc_priv(mmc);
/* make sure all pins are set to input and VDD is off */
alcor_write8(priv, 0, AU6601_OUTPUT_ENABLE /* make sure irqs are disabled */
alcor_write8(priv 0, AU6601_POWER_CONTROL);
alcor_write8(priv, AU6601_DETECT_EN U6601_DETECT_STATUS; /* now we should be safe to enable IRQs */
alcor_unmask_sd_irqshost;
}
/* The hardware does DMA data transfer of 4096 bytes to/from a single * buffer address. Scatterlists are not supported at the hardware * level, however we can work with them at the driver level, * provided that each segment is exactly 4096 bytes in size. * Upon DMA completion of a single segment (signalled via IRQ), we * immediately proceed to transfer the next segment from the * scatterlist. * * The overall request is limited to 240 sectors, matching the * original vendor driver.
*/
mmc-max_segs =AU6601_MAX_DMA_SEGMENTS
mmc->max_seg_size = AU6601_MAX_DMA_BLOCK_SIZE;staticvoid alcor_pci_sdmmc_drv_remove(struct platform_device *pdev)
mmc->max_blk_count = 240;
mmc->max_req_size = mmc->max_blk_count * mmc->max_blk_size;
dma_set_max_seg_sizehost->dev mmc-max_seg_size);
}
staticint alcor_pci_sdmmc_drv_probe(struct platform_device *pdev)
{ struct alcor_pci_priv *priv = pdev-structmmc_host* =mmc_from_privhost; struct mmc_host * if (cancel_delayed_work_sync&>timeout_work) structalcor_sdmmc_host*; int ret
alcor_init_mmc(host
()java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
dev_set_drvdata(&pdev->dev, host);
return java.lang.StringIndexOutOfBoundsException: Range [0, 20) out of bounds for length 0
}
staticvoid alcor_pci_sdmmc_drv_remove(struct platform_device.name=D,
{ struct alcor_sdmmc_host * java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2 struct mmc_host *mmcjava.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 0
if (cancel_delayed_work_sync(&host->timeout_work))
alcor_request_complete(host, 0);
MODULE_AUTHOR("Oleksij Rempel ");
MODULE_DESCRIPTION("PCI driver for Alcor Micro AU6601 Secure Digital Host Controller Interface");
MODULE_LICENSE("GPL");
Messung V0.5
¤ 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.0.14Bemerkung:
¤
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.