drivers/clk/davinci/psc.c

Source file repositories/reference/linux-study-clean/drivers/clk/davinci/psc.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/davinci/psc.c
Extension
.c
Size
13907 bytes
Lines
557
Domain
Driver Families
Bucket
drivers/clk
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 davinci_psc_data {
	struct clk_onecell_data clk_data;
	struct genpd_onecell_data pm_data;
	struct reset_controller_dev rcdev;
};

/**
 * struct davinci_lpsc_clk - LPSC clock structure
 * @dev: the device that provides this LPSC or NULL
 * @hw: clk_hw for the LPSC
 * @pm_domain: power domain for the LPSC
 * @genpd_clk: clock reference owned by @pm_domain
 * @regmap: PSC MMIO region
 * @md: Module domain (LPSC module id)
 * @pd: Power domain
 * @flags: LPSC_* quirk flags
 */
struct davinci_lpsc_clk {
	struct device *dev;
	struct clk_hw hw;
	struct generic_pm_domain pm_domain;
	struct clk *genpd_clk;
	struct regmap *regmap;
	u32 md;
	u32 pd;
	u32 flags;
};

#define to_davinci_psc_data(x) container_of(x, struct davinci_psc_data, x)
#define to_davinci_lpsc_clk(x) container_of(x, struct davinci_lpsc_clk, x)

/**
 * best_dev_name - get the "best" device name.
 * @dev: the device
 *
 * Returns the device tree compatible name if the device has a DT node,
 * otherwise return the device name. This is mainly needed because clkdev
 * lookups are limited to 20 chars for dev_id and when using device tree,
 * dev_name(dev) is much longer than that.
 */
static inline const char *best_dev_name(struct device *dev)
{
	const char *compatible;

	if (!of_property_read_string(dev->of_node, "compatible", &compatible))
		return compatible;

	return dev_name(dev);
}

static void davinci_lpsc_config(struct davinci_lpsc_clk *lpsc,
				enum davinci_lpsc_state next_state)
{
	u32 epcpr, pdstat, mdstat, ptstat;

	regmap_write_bits(lpsc->regmap, MDCTL(lpsc->md), MDSTAT_STATE_MASK,
			  next_state);

	if (lpsc->flags & LPSC_FORCE)
		regmap_write_bits(lpsc->regmap, MDCTL(lpsc->md), MDCTL_FORCE,
				  MDCTL_FORCE);

	regmap_read(lpsc->regmap, PDSTAT(lpsc->pd), &pdstat);
	if ((pdstat & PDSTAT_STATE_MASK) == 0) {
		regmap_write_bits(lpsc->regmap, PDCTL(lpsc->pd), PDCTL_NEXT,
				  PDCTL_NEXT);

		regmap_write(lpsc->regmap, PTCMD, BIT(lpsc->pd));

		regmap_read_poll_timeout(lpsc->regmap, EPCPR, epcpr,
					 epcpr & BIT(lpsc->pd), 0, 0);

		regmap_write_bits(lpsc->regmap, PDCTL(lpsc->pd), PDCTL_EPCGOOD,
				  PDCTL_EPCGOOD);
	} else {
		regmap_write(lpsc->regmap, PTCMD, BIT(lpsc->pd));
	}

	regmap_read_poll_timeout(lpsc->regmap, PTSTAT, ptstat,
				 !(ptstat & BIT(lpsc->pd)), 0, 0);

	regmap_read_poll_timeout(lpsc->regmap, MDSTAT(lpsc->md), mdstat,
				 (mdstat & MDSTAT_STATE_MASK) == next_state,
				 0, 0);
}

static int davinci_lpsc_clk_enable(struct clk_hw *hw)
{
	struct davinci_lpsc_clk *lpsc = to_davinci_lpsc_clk(hw);

Annotation

Implementation Notes