drivers/memory/samsung/exynos-srom.c

Source file repositories/reference/linux-study-clean/drivers/memory/samsung/exynos-srom.c

File Facts

System
Linux kernel
Corpus path
drivers/memory/samsung/exynos-srom.c
Extension
.c
Size
5317 bytes
Lines
211
Domain
Driver Families
Bucket
drivers/memory
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 exynos_srom_reg_dump {
	u32     offset;
	u32     value;
};

/**
 * struct exynos_srom: platform data for exynos srom controller driver.
 * @dev: platform device pointer
 * @reg_base: srom base address
 * @reg_offset: exynos_srom_reg_dump pointer to hold offset and its value.
 */
struct exynos_srom {
	struct device *dev;
	void __iomem *reg_base;
	struct exynos_srom_reg_dump *reg_offset;
};

static struct exynos_srom_reg_dump *
exynos_srom_alloc_reg_dump(const unsigned long *rdump,
			   unsigned long nr_rdump)
{
	struct exynos_srom_reg_dump *rd;
	unsigned int i;

	rd = kzalloc_objs(*rd, nr_rdump);
	if (!rd)
		return NULL;

	for (i = 0; i < nr_rdump; ++i)
		rd[i].offset = rdump[i];

	return rd;
}

static int exynos_srom_configure_bank(struct exynos_srom *srom,
				      struct device_node *np)
{
	u32 bank, width, pmc = 0;
	u32 timing[6];
	u32 cs, bw;

	if (of_property_read_u32(np, "reg", &bank))
		return -EINVAL;
	if (of_property_read_u32(np, "reg-io-width", &width))
		width = 1;
	if (of_property_read_bool(np, "samsung,srom-page-mode"))
		pmc = 1 << EXYNOS_SROM_BCX__PMC__SHIFT;
	if (of_property_read_u32_array(np, "samsung,srom-timing", timing,
				       ARRAY_SIZE(timing)))
		return -EINVAL;

	bank *= 4; /* Convert bank into shift/offset */

	cs = 1 << EXYNOS_SROM_BW__BYTEENABLE__SHIFT;
	if (width == 2)
		cs |= 1 << EXYNOS_SROM_BW__DATAWIDTH__SHIFT;

	bw = readl_relaxed(srom->reg_base + EXYNOS_SROM_BW);
	bw = (bw & ~(EXYNOS_SROM_BW__CS_MASK << bank)) | (cs << bank);
	writel_relaxed(bw, srom->reg_base + EXYNOS_SROM_BW);

	writel_relaxed(pmc | (timing[0] << EXYNOS_SROM_BCX__TACP__SHIFT) |
		       (timing[1] << EXYNOS_SROM_BCX__TCAH__SHIFT) |
		       (timing[2] << EXYNOS_SROM_BCX__TCOH__SHIFT) |
		       (timing[3] << EXYNOS_SROM_BCX__TACC__SHIFT) |
		       (timing[4] << EXYNOS_SROM_BCX__TCOS__SHIFT) |
		       (timing[5] << EXYNOS_SROM_BCX__TACS__SHIFT),
		       srom->reg_base + EXYNOS_SROM_BC0 + bank);

	return 0;
}

static int exynos_srom_probe(struct platform_device *pdev)
{
	struct device_node *np, *child;
	struct exynos_srom *srom;
	struct device *dev = &pdev->dev;
	bool bad_bank_config = false;

	np = dev->of_node;
	if (!np) {
		dev_err(&pdev->dev, "could not find device info\n");
		return -EINVAL;
	}

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

Annotation

Implementation Notes