drivers/soc/dove/pmu.c

Source file repositories/reference/linux-study-clean/drivers/soc/dove/pmu.c

File Facts

System
Linux kernel
Corpus path
drivers/soc/dove/pmu.c
Extension
.c
Size
11521 bytes
Lines
455
Domain
Driver Families
Bucket
drivers/soc
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 pmu_data {
	spinlock_t lock;
	struct device_node *of_node;
	void __iomem *pmc_base;
	void __iomem *pmu_base;
	struct irq_chip_generic *irq_gc;
	struct irq_domain *irq_domain;
#ifdef CONFIG_RESET_CONTROLLER
	struct reset_controller_dev reset;
#endif
};

/*
 * The PMU contains a register to reset various subsystems within the
 * SoC.  Export this as a reset controller.
 */
#ifdef CONFIG_RESET_CONTROLLER
#define rcdev_to_pmu(rcdev) container_of(rcdev, struct pmu_data, reset)

static int pmu_reset_reset(struct reset_controller_dev *rc, unsigned long id)
{
	struct pmu_data *pmu = rcdev_to_pmu(rc);
	unsigned long flags;
	u32 val;

	spin_lock_irqsave(&pmu->lock, flags);
	val = readl_relaxed(pmu->pmc_base + PMC_SW_RST);
	writel_relaxed(val & ~BIT(id), pmu->pmc_base + PMC_SW_RST);
	writel_relaxed(val | BIT(id), pmu->pmc_base + PMC_SW_RST);
	spin_unlock_irqrestore(&pmu->lock, flags);

	return 0;
}

static int pmu_reset_assert(struct reset_controller_dev *rc, unsigned long id)
{
	struct pmu_data *pmu = rcdev_to_pmu(rc);
	unsigned long flags;
	u32 val = ~BIT(id);

	spin_lock_irqsave(&pmu->lock, flags);
	val &= readl_relaxed(pmu->pmc_base + PMC_SW_RST);
	writel_relaxed(val, pmu->pmc_base + PMC_SW_RST);
	spin_unlock_irqrestore(&pmu->lock, flags);

	return 0;
}

static int pmu_reset_deassert(struct reset_controller_dev *rc, unsigned long id)
{
	struct pmu_data *pmu = rcdev_to_pmu(rc);
	unsigned long flags;
	u32 val = BIT(id);

	spin_lock_irqsave(&pmu->lock, flags);
	val |= readl_relaxed(pmu->pmc_base + PMC_SW_RST);
	writel_relaxed(val, pmu->pmc_base + PMC_SW_RST);
	spin_unlock_irqrestore(&pmu->lock, flags);

	return 0;
}

static const struct reset_control_ops pmu_reset_ops = {
	.reset = pmu_reset_reset,
	.assert = pmu_reset_assert,
	.deassert = pmu_reset_deassert,
};

static struct reset_controller_dev pmu_reset __initdata = {
	.ops = &pmu_reset_ops,
	.owner = THIS_MODULE,
	.nr_resets = 32,
};

static void __init pmu_reset_init(struct pmu_data *pmu)
{
	int ret;

	pmu->reset = pmu_reset;
	pmu->reset.of_node = pmu->of_node;

	ret = reset_controller_register(&pmu->reset);
	if (ret)
		pr_err("pmu: %s failed: %d\n", "reset_controller_register", ret);
}
#else
static void __init pmu_reset_init(struct pmu_data *pmu)
{
}
#endif

Annotation

Implementation Notes