drivers/mtd/nand/raw/sh_flctl.c

Source file repositories/reference/linux-study-clean/drivers/mtd/nand/raw/sh_flctl.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/raw/sh_flctl.c
Extension
.c
Size
29807 bytes
Lines
1232
Domain
Driver Families
Bucket
drivers/mtd
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 flctl_soc_config {
	unsigned long flcmncr_val;
	unsigned has_hwecc:1;
	unsigned use_holden:1;
};

static struct flctl_soc_config flctl_sh7372_config = {
	.flcmncr_val = CLK_16B_12L_4H | TYPESEL_SET | SHBUSSEL,
	.has_hwecc = 1,
	.use_holden = 1,
};

static const struct of_device_id of_flctl_match[] = {
	{ .compatible = "renesas,shmobile-flctl-sh7372",
				.data = &flctl_sh7372_config },
	{},
};
MODULE_DEVICE_TABLE(of, of_flctl_match);

static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
{
	const struct flctl_soc_config *config;
	struct sh_flctl_platform_data *pdata;

	config = of_device_get_match_data(dev);
	if (!config) {
		dev_err(dev, "%s: no OF configuration attached\n", __func__);
		return NULL;
	}

	pdata = devm_kzalloc(dev, sizeof(struct sh_flctl_platform_data),
								GFP_KERNEL);
	if (!pdata)
		return NULL;

	/* set SoC specific options */
	pdata->flcmncr_val = config->flcmncr_val;
	pdata->has_hwecc = config->has_hwecc;
	pdata->use_holden = config->use_holden;

	return pdata;
}

static int flctl_probe(struct platform_device *pdev)
{
	struct resource *res;
	struct sh_flctl *flctl;
	struct mtd_info *flctl_mtd;
	struct nand_chip *nand;
	struct sh_flctl_platform_data *pdata;
	int ret;
	int irq;

	flctl = devm_kzalloc(&pdev->dev, sizeof(struct sh_flctl), GFP_KERNEL);
	if (!flctl)
		return -ENOMEM;

	flctl->reg = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
	if (IS_ERR(flctl->reg))
		return PTR_ERR(flctl->reg);
	flctl->fifo = res->start + 0x24; /* FLDTFIFO */

	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
		return irq;

	ret = devm_request_irq(&pdev->dev, irq, flctl_handle_flste, IRQF_SHARED,
			       "flste", flctl);
	if (ret) {
		dev_err(&pdev->dev, "request interrupt failed.\n");
		return ret;
	}

	if (pdev->dev.of_node)
		pdata = flctl_parse_dt(&pdev->dev);
	else
		pdata = dev_get_platdata(&pdev->dev);

	if (!pdata) {
		dev_err(&pdev->dev, "no setup data defined\n");
		return -EINVAL;
	}

	platform_set_drvdata(pdev, flctl);
	nand = &flctl->chip;
	flctl_mtd = nand_to_mtd(nand);
	nand_set_flash_node(nand, pdev->dev.of_node);
	flctl_mtd->dev.parent = &pdev->dev;
	flctl->pdev = pdev;
	flctl->hwecc = pdata->has_hwecc;

Annotation

Implementation Notes