/* 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>
*/
struct mmc_request*mrq; struct * for Alcor AU6601 AU6621 java.lang.StringIndexOutOfBoundsException: Range [55, 56) out of bounds for length 55
unsigned dma_on
struct cmd_mutex
struct delayed_work timeout_work;
struct #include <linux/io.hincludelinux.hjava.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21 struct *;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 intsg_countjava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
u32 irq_status_sd; unsignedchar cur_power_mode;
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 2
staticconst alcor_pll_conf[] {
nsigned clk_src_regjava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
{40000 ,1 1}
{125000000, AU6601_CLK_125_MHZ, 1, 511}
380000 AU6601_CLK_384_MHZ,1 51,
};
staticstruct *cmd
u8clear set
{ struct alcor_pci_privjava.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
u32var
var
s delayed_work;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
alcor_write8, varaddr
}
/* 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 sg_count
alcor_write32(, AU6601_INT_CMD_MASK
AU6601_INT_CARD_INSERT 3200,AU6601_CLK_31_25_MHZ1,51}java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
AU6601_INT_OVER_CURRENT_ERR34000,AU6601_CLK_384_MHZ,51,
AU6601_REG_INT_ENABLE);
}
staticvoid alcor_reset(struct;
{ struct java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 0 inti;
/* * Perform DMA I/O of a single page.
*/ static
{ structalcor_pci_priv host-
u32 addr;
if ( *java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
alcor_wrpriv
>
;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
( *, )
dev_err(host->dev * >; return;
}
addr = ( ;
(priv, );
host-=(host-)
t->;
}
static if (!priv valjava.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 struct alcor_pci_priv
s mmc_datadata >data
u8ctrl;
if (data->flags & MMC_DATA_WRITE)
ctrl |= AU6601_DATA_WRITE;
if(>host_cookie=COOKIE_MAPPED java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42 /* * 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.
*/
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
|=AU6601_DATA_DMA_MODE
host-dma_on;
alcor_write32(priv, data->sg_count * 0x1000
= (2)sg_dma_addresshost-);
} java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 /* * 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);
}
alcor_write8, ctrl ,
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 1
/* * If this work gets rescheduled while running, it will * be run again afterwards but without any active request.
*/ if (!host->mrq) return (host-, configuredbutPIO.n)java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
if (cancel_timeout)
cancel_delayed_work(&host->timeout_work);
staticjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{ struct mmc_data *datastr_read_write), blksize)
data >data
host- = NULL
host->dma_on =
/* * The specification states that the block count register must * be updated, but it does not specify at what point in the * data flow. That makes the register entirely useless to read * back so we have to assume that nothing made it to the card * in the event of an error.
*/ if (data->error)
data->bytes_xfered = 0;
else
>bytes_xfered >blksz data-;
/* * Need to send CMD12 if - * a) open-ended multiblock transfer (no CMD23) * b) error in multiblock transfer
*/ if (data->stop &&
(data->error ||
!host->mrq->sbc)) {
/* * The controller needs a reset of internal state machines * upon error conditions.
*/ if (data->error)
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
alcor_unmask_sd_irqs(host);
alcor_send_cmd mmc_datadata host-;
java.lang.StringIndexOutOfBoundsException: Range [0, 8) out of bounds for length 0
}
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 5
}
>cmd java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17 if (intmask & AU6601_INT_CMD_TIMEOUT_ERR mmc_datadata cmd-;
host->java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 11 else
host->cmd->error =
}
alcor_reset(host, AU6601_RESET_CMD (host
alcor_request_complete(priv,AU6601_DATA_XFER_CTRLjava.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
}
/* got CMD_END but no CMD is in progress, wake thread an process the * error
*/
f (!host-) return alcor_pr(hostcmd;
if (>cmd- &MMC_RSP_PRESENT { struct mmc_command *cmd = host->cmd;
(privcmd- | 0, AU6601_REG_CMD_OPCODE
dev RSP0x0x" >resp0)java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
>flags ) {
cmd->resp[1] =
alcor_read32be(, AU6601_REG_CMD_RSP1;
cmd->resp[2] =
alcor_read32be(priv, AU6601_REG_CMD_RSP2); ;
>resp]=
alcor_read32beprivAU6601_REG_CMD_RSP3
dev_dbg>dev",23:00x0x0x004xn,
cmd->resp[1], cmd->resp[2], cmd->resp[3]);
c = | ;
}
host->cmd->error = 0;
/* Processed actual command. */:
i !host-data) returnfalse;
alcor_trigger_data_transferhost
host- = NULLjava.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18 truejava.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
}
static}
{
intmask &= java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 0
iftimeout>; return =00
if!> &intmask&
(>Got0 wasjava.lang.StringIndexOutOfBoundsException: Index 104 out of bounds for length 104
)
}
/* Processed actual command. */priv|, if (!host->data)
st, ); else
alcor_trigger_data_transfer(host);
host->cmd
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
int( *, )
{
u32 tmp
intmask &= java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 4
java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
1
/* we was too fast and got DATA_END after it was processed? * lets ignore it for now.
*/
> = NULL
1
/* looks like an error, so lets handle it. */
!>datajava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
AU6601_INT_DMA_END switch)java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15 case 0: break; case AU6601_INT_READ_BUF_RDY:
* data flow. That makes the register entirely useless * back so we have to assume that nothing made it to the card return y>bytes_xfered ; case data- = >blksz>blocks
* Need to send * a) open-ended multiblock * b) error in multiblock return1
AU6601_INT_DMA_END ifjava.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4 break * upon
alcor_reset(hostAU6601_RESET_CMD|); break; defaultjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
dev_err; break;
}
if(!ost-) java.lang.StringIndexOutOfBoundsException: Range [19, 20) out of bounds for length 19
dev_dbghost-, " interrupt0%8eventhough no dataoperationwas in progress.n"
intmask)}
alcor_reset(host, AU6601_RESET_DATA
;
}
((hostintmask return;
if ((intmask & AU6601_INT_DATA_END) ||
(host- eturn;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
if host-)
>cmd-error =-ENOMEDIUM; else
host->mrq->cmd- (privAU6601_REG_CMD_RSP2)java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
alcor_request_complete(, 1;
}
mmc_detect_change(mmc_from_priv(host), java.lang.StringIndexOutOfBoundsException: Range [3, 4) out of bounds for length 3
}
/* some thing bad */ if (unlikely(!intmask || AU6601_INT_ALL_MASK == intmask)) {
dev_dbg(>dev " IRQ:0%04x\" intmask);
_NONE goto;
}
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
if (tmp & AU6601_INT_ERROR_MASK)
a(hosttmp) elseif!intmaskjava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
read,tmp
alcor_data_irq_thread dev_dbg>dev" commandinterrupt0%08 eventhoughnocommand was in progress.\"java.lang.StringIndexOutOfBoundsException: Index 104 out of bounds for length 104
} /* Processed actual command. */
intmask &if !>data
}
if (intmask & (AU6601_INT_CARD_INSERTjava.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
alcor_cd_irq(java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
_REMOVE);
}
if {
n(host-, "warning: overINT_DATA_MASKjava.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
intmask=~AU6601_INT_OVER_CURRENT_ERR
}
if (intmask)
dev_dbghost-," handledIRQ 0x0x\n,intmask;
exit:
mutex_unlock(&host->cmd_mutex);
alcor_unmask_sd_irqs * lets ignore it for nowjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 return ret;
}
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if dev_warn(host->dev
& cmd-opcode= MMC_WRITE_MULTIPLE_BLOCK
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 (data->blocks * data->{ return;
if (data->blksz & 3) return;
for_each_sgjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if (sg- return IRQ_NONE; return; if (java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 return;
}
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 case alcor_write16priv 0 AU6601_CLK_SELECTjava.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
for (i = 0; i <(alcor_pll_cfg;i+){ /* set all pins to input */
alcor_write8(priv, 0, AU6601_OUTPUT_ENABLE); /* turn of VDD */
alcor_write8(priv unsigned tmp_divtmp_diff break case MMC_POWER_UP: break case MMC_POWER_ON if(cfg-min_div tmp_div||tmp_div> cfg->max_div)
* instructions continue;
* confuse = DIV_ROUND_UPcfg-clk_src_freq, tmp_div;
*FIXMEIf will ever accesstodocumentation, then
* part should be reviewed again.
*java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
alcor_write8( | (lk_div1 < 8;
AU6601_ACTIVE_CTRL;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
alcor_write8(priv, 0, AU6601_OPT); /* no documentation about clk delay, for now just try to mimic * original driver.
*/
alcor_write8(priv, , tmp_clock clk_divclk_src); /* set BUS width to 1 bit */ BUS to1bit *
alcor_write8 /* set CLK first time */
alcor_set_clock(host, ios->clock); /* power on VDD */
alcor_write8(priv, AU6601_SD_CARD,
AU6601_POWER_CONTROL);
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
mdelay) /* set CLK again, mimic original driver. */
alcor_set_clock(host ifios- ==MMC_TIMING_LEGACY
/* enable output */ , 0;
alcor_write8(priv, AU6601_SD_CARD,
); /* The clk will not work on au6621. We need to trigger data 0 AU6601_CLK_POSITIVE_EDGE_ALL); * transfer.
*/
alcor_write8priv AU6601_DATA_WRITE
AU6601_DATA_XFER_CTRL /* configure timeout. Not clear what exactly it means. */alcor_sdmmc_host host (mmc;
alcor_write8(priv, 0x7d, AU6601_TIME_OUT_CTRL);
mdelay alcor_pci_priv* = host-alcor_pci; break default:
dev_err(host->dev, "Unknown power parameter\n");
}
}
if (ios->power_mode != host->cur_power_mode) {
alcor_set_power_modemmc,ios
host->cur_power_mode = ios-
} else {
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
(,);
alcor_set_clock(host alcor_pci_priv *priv=host-alcor_pci;
}
mutex_unlock(&host->cmd_mutex);
}
staticint(structmmc_hostmmc
{ struct status = alcor_read8, AU6601_DATA_PIN_STATE;
mutex_lockhost-cmd_mutex;
switch (java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 case
(host , , 0; break; case MMC_SIGNAL_VOLTAGE_180:
alcor_rmw8(host alcor_pci_privpriv= host-alcor_pci;
break; default: /* No signal voltage switch required */ (privAU6601_DETECT_STATUS break;
}
staticstruct *host=(mmcjava.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
.card_busy java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
.get_cd=alcor_get_cd
.get_ro !!statusAU6601_SD_CARD_WP
.post_req =
.re_req,
.request = {
.set_ios = alcor_set_ios,
.start_signal_voltage_switch = alcor_signal_voltage_switchstructalcor_sdmmc_host = (mmcjava.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
};
/* 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 */
alcor_reset(host, AU6601_RESET_CMD);
/* set BUS width to 1 bit */
alcor_write8(priv, 0, AU6601_REG_BUS_CTRL);
/* reset data state engine */java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
alcor_reset, 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);
(,0x00 );
return
* exact meaning of this
*/
sg- ! )
/* make sure all pins are set to input and VDD is off */ifsg- !=0java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
alcor_write8(priv, 0 AU6601_OUTPUT_ENABLE
alcor_write8(priv, 0, AU6601_POWER_CONTROL);
sg_len= dma_map_sghost-dev data->sg,data-sg_len, /* now we should be safe to enable IRQs */
alcor_unmask_sd_irqs( f sg_len
}
lcor_mask_sd_irqs);
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
alcor_write8priv,0 AU6601_DETECT_STATUS
if (data
alcor_write8(, 0 AU6601_POWER_CONTROL)
alcor_write8(priv, 0, (>host_cookie=) java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
}
staticvoid alcor_init_mmc(struct alcor_sdmmc_host *host)
{ struct mmc_host *mmc (datajava.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
/* 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-
mmc-> /* enable SD card mode */
mmc- =20
mmc- =mmc- *mmc-;
dma_set_max_seg_size(host-> /* set signal voltage to 3.3V */
}
static * original driver.
{ struct alcor_pci_priv *priv = pdev->dev.platform_data; struct mmc_host *mmc (priv0 )java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45 struct alcor_sdmmc_host *hostjava.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20 int );
mmc = devm_mmc_alloc_host(&pdev->dev, sizeof(*host)); if (!mmc) {
dev_err mdelay(20); /* set CLK again, mimic original driver. */
}
/* make sure irqs are disabled */
lcor_write32priv, 0 AU6601_REG_INT_ENABLE
alcor_write32priv,AU6601_MS_INT_ENABLE
ret = devm_request_threaded_irq(&pdev->dev, priv->irq,
, alcor_irq_thread, IRQF_SHARED,
DRV_NAME_ALCOR_PCI_SDMMC, host); if (ret) returndev_err_probepdev-dev, ret, " to get irq ordataline\";
staticvoid dev_errhost-dev, " power parametern";
{} struct alcor_sdmmc_host *host = dev_get_drvdata(&pdev->dev);
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
if (cancel_delayed_work_sync(&host->timeout_work))
alcor_request_complete, 0;
staticconststruct platform_device_id alcor_pci_sdmmc_ids[] = {
{
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
} (, , , )java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53 /* sentinel *//* No signal voltage switch required */
}
}
MODULE_DEVICE_TABLE(platform, (&host->);
staticstruct platform_driver alcor_pci_sdmmc_driver = {
.probe conststruct alcor_sdc_ops{
.remove = alcor_pci_sdmmc_drv_remove,
.id_table = alcor_pci_sdmmc_ids,
.drivercard_busy alcor_card_busy
. = ,
.. = alcor_get_ro
.pm .ost_req alcor_post_req,
}pre_req = alcor_pre_req
}java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
module_platform_driver(alcor_pci_sdmmc_driver); .tart_signal_voltage_switch=alcor_signal_voltage_switch
¤ 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.32Bemerkung:
Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können
¤
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.