drivers/rtc/rtc-imxdi.c

Source file repositories/reference/linux-study-clean/drivers/rtc/rtc-imxdi.c

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-imxdi.c
Extension
.c
Size
25016 bytes
Lines
872
Domain
Driver Families
Bucket
drivers/rtc
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 imxdi_dev {
	struct platform_device *pdev;
	struct rtc_device *rtc;
	void __iomem *ioaddr;
	struct clk *clk;
	u32 dsr;
	spinlock_t irq_lock;
	wait_queue_head_t write_wait;
	struct mutex write_mutex;
	struct work_struct work;
};

/* Some background:
 *
 * The DryIce unit is a complex security/tamper monitor device. To be able do
 * its job in a useful manner it runs a bigger statemachine to bring it into
 * security/tamper failure state and once again to bring it out of this state.
 *
 * This unit can be in one of three states:
 *
 * - "NON-VALID STATE"
 *   always after the battery power was removed
 * - "FAILURE STATE"
 *   if one of the enabled security events has happened
 * - "VALID STATE"
 *   if the unit works as expected
 *
 * Everything stops when the unit enters the failure state including the RTC
 * counter (to be able to detect the time the security event happened).
 *
 * The following events (when enabled) let the DryIce unit enter the failure
 * state:
 *
 * - wire-mesh-tamper detect
 * - external tamper B detect
 * - external tamper A detect
 * - temperature tamper detect
 * - clock tamper detect
 * - voltage tamper detect
 * - RTC counter overflow
 * - monotonic counter overflow
 * - external boot
 *
 * If we find the DryIce unit in "FAILURE STATE" and the TDCHL cleared, we
 * can only detect this state. In this case the unit is completely locked and
 * must force a second "SYSTEM POR" to bring the DryIce into the
 * "NON-VALID STATE" + "FAILURE STATE" where a recovery is possible.
 * If the TDCHL is set in the "FAILURE STATE" we are out of luck. In this case
 * a battery power cycle is required.
 *
 * In the "NON-VALID STATE" + "FAILURE STATE" we can clear the "FAILURE STATE"
 * and recover the DryIce unit. By clearing the "NON-VALID STATE" as the last
 * task, we bring back this unit into life.
 */

/*
 * Do a write into the unit without interrupt support.
 * We do not need to check the WEF here, because the only reason this kind of
 * write error can happen is if we write to the unit twice within the 122 us
 * interval. This cannot happen, since we are using this function only while
 * setting up the unit.
 */
static void di_write_busy_wait(const struct imxdi_dev *imxdi, u32 val,
			       unsigned reg)
{
	/* do the register write */
	writel(val, imxdi->ioaddr + reg);

	/*
	 * now it takes four 32,768 kHz clock cycles to take
	 * the change into effect = 122 us
	 */
	usleep_range(130, 200);
}

static void di_report_tamper_info(struct imxdi_dev *imxdi,  u32 dsr)
{
	u32 dtcr;

	dtcr = readl(imxdi->ioaddr + DTCR);

	dev_emerg(&imxdi->pdev->dev, "DryIce tamper event detected\n");
	/* the following flags force a transition into the "FAILURE STATE" */
	if (dsr & DSR_VTD)
		dev_emerg(&imxdi->pdev->dev, "%sVoltage Tamper Event\n",
			  dtcr & DTCR_VTE ? "" : "Spurious ");

	if (dsr & DSR_CTD)
		dev_emerg(&imxdi->pdev->dev, "%s32768 Hz Clock Tamper Event\n",
			  dtcr & DTCR_CTE ? "" : "Spurious ");

Annotation

Implementation Notes