drivers/mmc/host/meson-mx-sdio.c

Source file repositories/reference/linux-study-clean/drivers/mmc/host/meson-mx-sdio.c

File Facts

System
Linux kernel
Corpus path
drivers/mmc/host/meson-mx-sdio.c
Extension
.c
Size
21596 bytes
Lines
771
Domain
Driver Families
Bucket
drivers/mmc
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct meson_mx_mmc_host_clkc {
	struct clk_divider		cfg_div;
	struct clk_fixed_factor		fixed_div2;
};

struct meson_mx_mmc_host {
	struct device			*controller_dev;

	struct clk			*cfg_div_clk;
	struct regmap			*regmap;
	int				irq;
	spinlock_t			irq_lock;

	struct timer_list		cmd_timeout;

	unsigned int			slot_id;
	struct mmc_host			*mmc;

	struct mmc_request		*mrq;
	struct mmc_command		*cmd;
	int				error;
};

static void meson_mx_mmc_soft_reset(struct meson_mx_mmc_host *host)
{
	regmap_write(host->regmap, MESON_MX_SDIO_IRQC,
		     MESON_MX_SDIO_IRQC_SOFT_RESET);
	udelay(2);
}

static struct mmc_command *meson_mx_mmc_get_next_cmd(struct mmc_command *cmd)
{
	if (cmd->opcode == MMC_SET_BLOCK_COUNT && !cmd->error)
		return cmd->mrq->cmd;
	else if (mmc_op_multi(cmd->opcode) &&
		 (!cmd->mrq->sbc || cmd->error || cmd->data->error))
		return cmd->mrq->stop;
	else
		return NULL;
}

static void meson_mx_mmc_start_cmd(struct mmc_host *mmc,
				   struct mmc_command *cmd)
{
	struct meson_mx_mmc_host *host = mmc_priv(mmc);
	unsigned int pack_size;
	unsigned long irqflags, timeout;
	u32 send = 0, ext = 0;

	host->cmd = cmd;

	if (cmd->busy_timeout)
		timeout = msecs_to_jiffies(cmd->busy_timeout);
	else
		timeout = msecs_to_jiffies(1000);

	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_R1:
	case MMC_RSP_R1B:
	case MMC_RSP_R3:
		/* 7 (CMD) + 32 (response) + 7 (CRC) -1 */
		send |= FIELD_PREP(MESON_MX_SDIO_SEND_CMD_RESP_BITS_MASK, 45);
		break;
	case MMC_RSP_R2:
		/* 7 (CMD) + 120 (response) + 7 (CRC) -1 */
		send |= FIELD_PREP(MESON_MX_SDIO_SEND_CMD_RESP_BITS_MASK, 133);
		send |= MESON_MX_SDIO_SEND_RESP_CRC7_FROM_8;
		break;
	default:
		break;
	}

	if (!(cmd->flags & MMC_RSP_CRC))
		send |= MESON_MX_SDIO_SEND_RESP_WITHOUT_CRC7;

	if (cmd->flags & MMC_RSP_BUSY)
		send |= MESON_MX_SDIO_SEND_CHECK_DAT0_BUSY;

	if (cmd->data) {
		send |= FIELD_PREP(MESON_MX_SDIO_SEND_REPEAT_PACKAGE_TIMES_MASK,
				   (cmd->data->blocks - 1));

		pack_size = cmd->data->blksz * BITS_PER_BYTE;
		if (mmc->ios.bus_width == MMC_BUS_WIDTH_4)
			pack_size += MESON_MX_SDIO_RESPONSE_CRC16_BITS * 4;
		else
			pack_size += MESON_MX_SDIO_RESPONSE_CRC16_BITS * 1;

		ext |= FIELD_PREP(MESON_MX_SDIO_EXT_DATA_RW_NUMBER_MASK,
				  pack_size);

Annotation

Implementation Notes