drivers/ata/pata_arasan_cf.c

Source file repositories/reference/linux-study-clean/drivers/ata/pata_arasan_cf.c

File Facts

System
Linux kernel
Corpus path
drivers/ata/pata_arasan_cf.c
Extension
.c
Size
26411 bytes
Lines
970
Domain
Driver Families
Bucket
drivers/ata
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 arasan_cf_dev {
	/* pointer to ata_host structure */
	struct ata_host *host;
	/* clk structure */
	struct clk *clk;

	/* physical base address of controller */
	dma_addr_t pbase;
	/* virtual base address of controller */
	void __iomem *vbase;
	/* irq number*/
	int irq;

	/* status to be updated to framework regarding DMA transfer */
	u8 dma_status;
	/* Card is present or Not */
	u8 card_present;

	/* dma specific */
	/* Completion for transfer complete interrupt from controller */
	struct completion cf_completion;
	/* Completion for DMA transfer complete. */
	struct completion dma_completion;
	/* Dma channel allocated */
	struct dma_chan *dma_chan;
	/* Mask for DMA transfers */
	dma_cap_mask_t mask;
	/* DMA transfer work */
	struct work_struct work;
	/* DMA delayed finish work */
	struct delayed_work dwork;
	/* qc to be transferred using DMA */
	struct ata_queued_cmd *qc;
};

static const struct scsi_host_template arasan_cf_sht = {
	ATA_BASE_SHT(DRIVER_NAME),
	.dma_boundary = 0xFFFFFFFFUL,
};

static void cf_dumpregs(struct arasan_cf_dev *acdev)
{
	struct device *dev = acdev->host->dev;

	dev_dbg(dev, ": =========== REGISTER DUMP ===========");
	dev_dbg(dev, ": CFI_STS: %x", readl(acdev->vbase + CFI_STS));
	dev_dbg(dev, ": IRQ_STS: %x", readl(acdev->vbase + IRQ_STS));
	dev_dbg(dev, ": IRQ_EN: %x", readl(acdev->vbase + IRQ_EN));
	dev_dbg(dev, ": OP_MODE: %x", readl(acdev->vbase + OP_MODE));
	dev_dbg(dev, ": CLK_CFG: %x", readl(acdev->vbase + CLK_CFG));
	dev_dbg(dev, ": TM_CFG: %x", readl(acdev->vbase + TM_CFG));
	dev_dbg(dev, ": XFER_CTR: %x", readl(acdev->vbase + XFER_CTR));
	dev_dbg(dev, ": GIRQ_STS: %x", readl(acdev->vbase + GIRQ_STS));
	dev_dbg(dev, ": GIRQ_STS_EN: %x", readl(acdev->vbase + GIRQ_STS_EN));
	dev_dbg(dev, ": GIRQ_SGN_EN: %x", readl(acdev->vbase + GIRQ_SGN_EN));
	dev_dbg(dev, ": =====================================");
}

/* Enable/Disable global interrupts shared between CF and XD ctrlr. */
static void cf_ginterrupt_enable(struct arasan_cf_dev *acdev, bool enable)
{
	/* enable should be 0 or 1 */
	writel(enable, acdev->vbase + GIRQ_STS_EN);
	writel(enable, acdev->vbase + GIRQ_SGN_EN);
}

/* Enable/Disable CF interrupts */
static inline void
cf_interrupt_enable(struct arasan_cf_dev *acdev, u32 mask, bool enable)
{
	u32 val = readl(acdev->vbase + IRQ_EN);
	/* clear & enable/disable irqs */
	if (enable) {
		writel(mask, acdev->vbase + IRQ_STS);
		writel(val | mask, acdev->vbase + IRQ_EN);
	} else
		writel(val & ~mask, acdev->vbase + IRQ_EN);
}

static inline void cf_card_reset(struct arasan_cf_dev *acdev)
{
	u32 val = readl(acdev->vbase + OP_MODE);

	writel(val | CARD_RESET, acdev->vbase + OP_MODE);
	udelay(200);
	writel(val & ~CARD_RESET, acdev->vbase + OP_MODE);
}

static inline void cf_ctrl_reset(struct arasan_cf_dev *acdev)
{

Annotation

Implementation Notes