^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright 2010 Orex Computed Radiography
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This driver uses the 47-bit 32 kHz counter in the Freescale DryIce block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * to implement a Linux RTC. Times and alarms are truncated to seconds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Since the RTC framework performs API locking via rtc->ops_lock the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * only simultaneous accesses we need to deal with is updating DryIce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * registers while servicing an alarm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Note that reading the DSR (DryIce Status Register) automatically clears
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * the WCF (Write Complete Flag). All DryIce writes are synchronized to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * LP (Low Power) domain and set the WCF upon completion. Writes to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * DIER (DryIce Interrupt Enable Register) are the only exception. These
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * occur at normal bus speeds and do not set WCF. Periodic interrupts are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * not supported by the hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/rtc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* DryIce Register Definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define DTCMR 0x00 /* Time Counter MSB Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define DTCLR 0x04 /* Time Counter LSB Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define DCAMR 0x08 /* Clock Alarm MSB Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define DCALR 0x0c /* Clock Alarm LSB Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define DCAMR_UNSET 0xFFFFFFFF /* doomsday - 1 sec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define DCR 0x10 /* Control Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define DCR_TDCHL (1 << 30) /* Tamper-detect configuration hard lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define DCR_TDCSL (1 << 29) /* Tamper-detect configuration soft lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define DCR_KSSL (1 << 27) /* Key-select soft lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define DCR_MCHL (1 << 20) /* Monotonic-counter hard lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define DCR_MCSL (1 << 19) /* Monotonic-counter soft lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define DCR_TCHL (1 << 18) /* Timer-counter hard lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define DCR_TCSL (1 << 17) /* Timer-counter soft lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define DCR_FSHL (1 << 16) /* Failure state hard lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define DCR_TCE (1 << 3) /* Time Counter Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define DCR_MCE (1 << 2) /* Monotonic Counter Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define DSR 0x14 /* Status Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define DSR_WTD (1 << 23) /* Wire-mesh tamper detected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define DSR_ETBD (1 << 22) /* External tamper B detected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define DSR_ETAD (1 << 21) /* External tamper A detected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define DSR_EBD (1 << 20) /* External boot detected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define DSR_SAD (1 << 19) /* SCC alarm detected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define DSR_TTD (1 << 18) /* Temperature tamper detected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define DSR_CTD (1 << 17) /* Clock tamper detected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define DSR_VTD (1 << 16) /* Voltage tamper detected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define DSR_WBF (1 << 10) /* Write Busy Flag (synchronous) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define DSR_WNF (1 << 9) /* Write Next Flag (synchronous) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define DSR_WCF (1 << 8) /* Write Complete Flag (synchronous)*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define DSR_WEF (1 << 7) /* Write Error Flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define DSR_CAF (1 << 4) /* Clock Alarm Flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define DSR_MCO (1 << 3) /* monotonic counter overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define DSR_TCO (1 << 2) /* time counter overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define DSR_NVF (1 << 1) /* Non-Valid Flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define DSR_SVF (1 << 0) /* Security Violation Flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define DIER 0x18 /* Interrupt Enable Reg (synchronous) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define DIER_WNIE (1 << 9) /* Write Next Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define DIER_WCIE (1 << 8) /* Write Complete Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define DIER_WEIE (1 << 7) /* Write Error Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define DIER_CAIE (1 << 4) /* Clock Alarm Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define DIER_SVIE (1 << 0) /* Security-violation Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define DMCR 0x1c /* DryIce Monotonic Counter Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define DTCR 0x28 /* DryIce Tamper Configuration Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define DTCR_MOE (1 << 9) /* monotonic overflow enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define DTCR_TOE (1 << 8) /* time overflow enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define DTCR_WTE (1 << 7) /* wire-mesh tamper enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define DTCR_ETBE (1 << 6) /* external B tamper enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define DTCR_ETAE (1 << 5) /* external A tamper enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define DTCR_EBE (1 << 4) /* external boot tamper enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define DTCR_SAIE (1 << 3) /* SCC enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define DTCR_TTE (1 << 2) /* temperature tamper enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define DTCR_CTE (1 << 1) /* clock tamper enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define DTCR_VTE (1 << 0) /* voltage tamper enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define DGPR 0x3c /* DryIce General Purpose Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * struct imxdi_dev - private imxdi rtc data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * @pdev: pointer to platform dev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * @rtc: pointer to rtc struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * @ioaddr: IO registers pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * @clk: input reference clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * @dsr: copy of the DSR register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * @irq_lock: interrupt enable register (DIER) lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @write_wait: registers write complete queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * @write_mutex: serialize registers write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * @work: schedule alarm work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct imxdi_dev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct rtc_device *rtc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) void __iomem *ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u32 dsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) spinlock_t irq_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) wait_queue_head_t write_wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct mutex write_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* Some background:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * The DryIce unit is a complex security/tamper monitor device. To be able do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * its job in a useful manner it runs a bigger statemachine to bring it into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * security/tamper failure state and once again to bring it out of this state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * This unit can be in one of three states:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * - "NON-VALID STATE"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * always after the battery power was removed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * - "FAILURE STATE"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * if one of the enabled security events has happened
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * - "VALID STATE"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * if the unit works as expected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * Everything stops when the unit enters the failure state including the RTC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * counter (to be able to detect the time the security event happened).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * The following events (when enabled) let the DryIce unit enter the failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * state:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * - wire-mesh-tamper detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * - external tamper B detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * - external tamper A detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * - temperature tamper detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * - clock tamper detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * - voltage tamper detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * - RTC counter overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * - monotonic counter overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * - external boot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * If we find the DryIce unit in "FAILURE STATE" and the TDCHL cleared, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * can only detect this state. In this case the unit is completely locked and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * must force a second "SYSTEM POR" to bring the DryIce into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * "NON-VALID STATE" + "FAILURE STATE" where a recovery is possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * If the TDCHL is set in the "FAILURE STATE" we are out of luck. In this case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * a battery power cycle is required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * In the "NON-VALID STATE" + "FAILURE STATE" we can clear the "FAILURE STATE"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * and recover the DryIce unit. By clearing the "NON-VALID STATE" as the last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * task, we bring back this unit into life.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * Do a write into the unit without interrupt support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * We do not need to check the WEF here, because the only reason this kind of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * write error can happen is if we write to the unit twice within the 122 us
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * interval. This cannot happen, since we are using this function only while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * setting up the unit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static void di_write_busy_wait(const struct imxdi_dev *imxdi, u32 val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) unsigned reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* do the register write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) writel(val, imxdi->ioaddr + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * now it takes four 32,768 kHz clock cycles to take
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * the change into effect = 122 us
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) usleep_range(130, 200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static void di_report_tamper_info(struct imxdi_dev *imxdi, u32 dsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) u32 dtcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) dtcr = readl(imxdi->ioaddr + DTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) dev_emerg(&imxdi->pdev->dev, "DryIce tamper event detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* the following flags force a transition into the "FAILURE STATE" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (dsr & DSR_VTD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) dev_emerg(&imxdi->pdev->dev, "%sVoltage Tamper Event\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) dtcr & DTCR_VTE ? "" : "Spurious ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (dsr & DSR_CTD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) dev_emerg(&imxdi->pdev->dev, "%s32768 Hz Clock Tamper Event\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) dtcr & DTCR_CTE ? "" : "Spurious ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (dsr & DSR_TTD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) dev_emerg(&imxdi->pdev->dev, "%sTemperature Tamper Event\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) dtcr & DTCR_TTE ? "" : "Spurious ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (dsr & DSR_SAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) dev_emerg(&imxdi->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) "%sSecure Controller Alarm Event\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) dtcr & DTCR_SAIE ? "" : "Spurious ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (dsr & DSR_EBD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) dev_emerg(&imxdi->pdev->dev, "%sExternal Boot Tamper Event\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) dtcr & DTCR_EBE ? "" : "Spurious ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (dsr & DSR_ETAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) dev_emerg(&imxdi->pdev->dev, "%sExternal Tamper A Event\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) dtcr & DTCR_ETAE ? "" : "Spurious ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (dsr & DSR_ETBD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) dev_emerg(&imxdi->pdev->dev, "%sExternal Tamper B Event\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) dtcr & DTCR_ETBE ? "" : "Spurious ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (dsr & DSR_WTD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) dev_emerg(&imxdi->pdev->dev, "%sWire-mesh Tamper Event\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) dtcr & DTCR_WTE ? "" : "Spurious ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (dsr & DSR_MCO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) dev_emerg(&imxdi->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) "%sMonotonic-counter Overflow Event\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) dtcr & DTCR_MOE ? "" : "Spurious ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (dsr & DSR_TCO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) dev_emerg(&imxdi->pdev->dev, "%sTimer-counter Overflow Event\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) dtcr & DTCR_TOE ? "" : "Spurious ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static void di_what_is_to_be_done(struct imxdi_dev *imxdi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) const char *power_supply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) dev_emerg(&imxdi->pdev->dev, "Please cycle the %s power supply in order to get the DryIce/RTC unit working again\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) power_supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static int di_handle_failure_state(struct imxdi_dev *imxdi, u32 dsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) u32 dcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) dev_dbg(&imxdi->pdev->dev, "DSR register reports: %08X\n", dsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* report the cause */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) di_report_tamper_info(imxdi, dsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) dcr = readl(imxdi->ioaddr + DCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (dcr & DCR_FSHL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* we are out of luck */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) di_what_is_to_be_done(imxdi, "battery");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * with the next SYSTEM POR we will transit from the "FAILURE STATE"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * into the "NON-VALID STATE" + "FAILURE STATE"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) di_what_is_to_be_done(imxdi, "main");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static int di_handle_valid_state(struct imxdi_dev *imxdi, u32 dsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* initialize alarm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) di_write_busy_wait(imxdi, DCAMR_UNSET, DCAMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) di_write_busy_wait(imxdi, 0, DCALR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* clear alarm flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (dsr & DSR_CAF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) di_write_busy_wait(imxdi, DSR_CAF, DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static int di_handle_invalid_state(struct imxdi_dev *imxdi, u32 dsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) u32 dcr, sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * lets disable all sources which can force the DryIce unit into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * the "FAILURE STATE" for now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) di_write_busy_wait(imxdi, 0x00000000, DTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /* and lets protect them at runtime from any change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) di_write_busy_wait(imxdi, DCR_TDCSL, DCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) sec = readl(imxdi->ioaddr + DTCMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (sec != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) dev_warn(&imxdi->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) "The security violation has happened at %u seconds\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * the timer cannot be set/modified if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * - the TCHL or TCSL bit is set in DCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) dcr = readl(imxdi->ioaddr + DCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (!(dcr & DCR_TCE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (dcr & DCR_TCHL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /* we are out of luck */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) di_what_is_to_be_done(imxdi, "battery");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (dcr & DCR_TCSL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) di_what_is_to_be_done(imxdi, "main");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * - the timer counter stops/is stopped if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * - its overflow flag is set (TCO in DSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * -> clear overflow bit to make it count again
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * - NVF is set in DSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * -> clear non-valid bit to make it count again
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * - its TCE (DCR) is cleared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * -> set TCE to make it count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * - it was never set before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * -> write a time into it (required again if the NVF was set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /* state handled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) di_write_busy_wait(imxdi, DSR_NVF, DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* clear overflow flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) di_write_busy_wait(imxdi, DSR_TCO, DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /* enable the counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) di_write_busy_wait(imxdi, dcr | DCR_TCE, DCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* set and trigger it to make it count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) di_write_busy_wait(imxdi, sec, DTCMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* now prepare for the valid state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return di_handle_valid_state(imxdi, __raw_readl(imxdi->ioaddr + DSR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static int di_handle_invalid_and_failure_state(struct imxdi_dev *imxdi, u32 dsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) u32 dcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * now we must first remove the tamper sources in order to get the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * device out of the "FAILURE STATE"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * To disable any of the following sources we need to modify the DTCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (dsr & (DSR_WTD | DSR_ETBD | DSR_ETAD | DSR_EBD | DSR_SAD |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) DSR_TTD | DSR_CTD | DSR_VTD | DSR_MCO | DSR_TCO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) dcr = __raw_readl(imxdi->ioaddr + DCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (dcr & DCR_TDCHL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * the tamper register is locked. We cannot disable the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * tamper detection. The TDCHL can only be reset by a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * DRYICE POR, but we cannot force a DRYICE POR in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * software because we are still in "FAILURE STATE".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * We need a DRYICE POR via battery power cycling....
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * out of luck!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * we cannot disable them without a DRYICE POR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) di_what_is_to_be_done(imxdi, "battery");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (dcr & DCR_TDCSL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* a soft lock can be removed by a SYSTEM POR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) di_what_is_to_be_done(imxdi, "main");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* disable all sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) di_write_busy_wait(imxdi, 0x00000000, DTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* clear the status bits now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) di_write_busy_wait(imxdi, dsr & (DSR_WTD | DSR_ETBD | DSR_ETAD |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) DSR_EBD | DSR_SAD | DSR_TTD | DSR_CTD | DSR_VTD |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) DSR_MCO | DSR_TCO), DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) dsr = readl(imxdi->ioaddr + DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if ((dsr & ~(DSR_NVF | DSR_SVF | DSR_WBF | DSR_WNF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) DSR_WCF | DSR_WEF)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) dev_warn(&imxdi->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) "There are still some sources of pain in DSR: %08x!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) dsr & ~(DSR_NVF | DSR_SVF | DSR_WBF | DSR_WNF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) DSR_WCF | DSR_WEF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * now we are trying to clear the "Security-violation flag" to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * get the DryIce out of this state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) di_write_busy_wait(imxdi, DSR_SVF, DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /* success? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) dsr = readl(imxdi->ioaddr + DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (dsr & DSR_SVF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) dev_crit(&imxdi->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) "Cannot clear the security violation flag. We are ending up in an endless loop!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* last resort */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) di_what_is_to_be_done(imxdi, "battery");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * now we have left the "FAILURE STATE" and ending up in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * "NON-VALID STATE" time to recover everything
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return di_handle_invalid_state(imxdi, dsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static int di_handle_state(struct imxdi_dev *imxdi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) u32 dsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) dsr = readl(imxdi->ioaddr + DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) switch (dsr & (DSR_NVF | DSR_SVF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) case DSR_NVF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) dev_warn(&imxdi->pdev->dev, "Invalid stated unit detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) rc = di_handle_invalid_state(imxdi, dsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) case DSR_SVF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) dev_warn(&imxdi->pdev->dev, "Failure stated unit detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) rc = di_handle_failure_state(imxdi, dsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) case DSR_NVF | DSR_SVF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) dev_warn(&imxdi->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) "Failure+Invalid stated unit detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) rc = di_handle_invalid_and_failure_state(imxdi, dsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) dev_notice(&imxdi->pdev->dev, "Unlocked unit detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) rc = di_handle_valid_state(imxdi, dsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * enable a dryice interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) static void di_int_enable(struct imxdi_dev *imxdi, u32 intr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) spin_lock_irqsave(&imxdi->irq_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) writel(readl(imxdi->ioaddr + DIER) | intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) imxdi->ioaddr + DIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) spin_unlock_irqrestore(&imxdi->irq_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * disable a dryice interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static void di_int_disable(struct imxdi_dev *imxdi, u32 intr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) spin_lock_irqsave(&imxdi->irq_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) writel(readl(imxdi->ioaddr + DIER) & ~intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) imxdi->ioaddr + DIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) spin_unlock_irqrestore(&imxdi->irq_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * This function attempts to clear the dryice write-error flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * A dryice write error is similar to a bus fault and should not occur in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * normal operation. Clearing the flag requires another write, so the root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * cause of the problem may need to be fixed before the flag can be cleared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static void clear_write_error(struct imxdi_dev *imxdi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /* clear the write error flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) writel(DSR_WEF, imxdi->ioaddr + DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /* wait for it to take effect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) for (cnt = 0; cnt < 1000; cnt++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if ((readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) dev_err(&imxdi->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) "ERROR: Cannot clear write-error flag!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * Write a dryice register and wait until it completes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * This function uses interrupts to determine when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * write has completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static int di_write_wait(struct imxdi_dev *imxdi, u32 val, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) /* serialize register writes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) mutex_lock(&imxdi->write_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /* enable the write-complete interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) di_int_enable(imxdi, DIER_WCIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) imxdi->dsr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /* do the register write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) writel(val, imxdi->ioaddr + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /* wait for the write to finish */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) ret = wait_event_interruptible_timeout(imxdi->write_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) imxdi->dsr & (DSR_WCF | DSR_WEF), msecs_to_jiffies(1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) rc = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) } else if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) dev_warn(&imxdi->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) "Write-wait timeout "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) "val = 0x%08x reg = 0x%08x\n", val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /* check for write error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (imxdi->dsr & DSR_WEF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) clear_write_error(imxdi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) mutex_unlock(&imxdi->write_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * read the seconds portion of the current time from the dryice time counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) struct imxdi_dev *imxdi = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) unsigned long now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) now = readl(imxdi->ioaddr + DTCMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) rtc_time64_to_tm(now, tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * set the seconds portion of dryice time counter and clear the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * fractional part.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static int dryice_rtc_set_time(struct device *dev, struct rtc_time *tm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct imxdi_dev *imxdi = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) u32 dcr, dsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) dcr = readl(imxdi->ioaddr + DCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) dsr = readl(imxdi->ioaddr + DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (!(dcr & DCR_TCE) || (dsr & DSR_SVF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (dcr & DCR_TCHL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* we are even more out of luck */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) di_what_is_to_be_done(imxdi, "battery");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if ((dcr & DCR_TCSL) || (dsr & DSR_SVF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /* we are out of luck for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) di_what_is_to_be_done(imxdi, "main");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* zero the fractional part first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) rc = di_write_wait(imxdi, 0, DTCLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) rc = di_write_wait(imxdi, rtc_tm_to_time64(tm), DTCMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return di_write_wait(imxdi, readl(imxdi->ioaddr + DCR) | DCR_TCE, DCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static int dryice_rtc_alarm_irq_enable(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) unsigned int enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) struct imxdi_dev *imxdi = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) di_int_enable(imxdi, DIER_CAIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) di_int_disable(imxdi, DIER_CAIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * read the seconds portion of the alarm register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * the fractional part of the alarm register is always zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct imxdi_dev *imxdi = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) u32 dcamr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) dcamr = readl(imxdi->ioaddr + DCAMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) rtc_time64_to_tm(dcamr, &alarm->time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /* alarm is enabled if the interrupt is enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) alarm->enabled = (readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* don't allow the DSR read to mess up DSR_WCF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) mutex_lock(&imxdi->write_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* alarm is pending if the alarm flag is set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) alarm->pending = (readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) mutex_unlock(&imxdi->write_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * set the seconds portion of dryice alarm register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct imxdi_dev *imxdi = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /* write the new alarm time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) rc = di_write_wait(imxdi, rtc_tm_to_time64(&alarm->time), DCAMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (alarm->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) di_int_enable(imxdi, DIER_CAIE); /* enable alarm intr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) di_int_disable(imxdi, DIER_CAIE); /* disable alarm intr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static const struct rtc_class_ops dryice_rtc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) .read_time = dryice_rtc_read_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) .set_time = dryice_rtc_set_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) .alarm_irq_enable = dryice_rtc_alarm_irq_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) .read_alarm = dryice_rtc_read_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) .set_alarm = dryice_rtc_set_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * interrupt handler for dryice "normal" and security violation interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) static irqreturn_t dryice_irq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) struct imxdi_dev *imxdi = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) u32 dsr, dier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) irqreturn_t rc = IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) dier = readl(imxdi->ioaddr + DIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) dsr = readl(imxdi->ioaddr + DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /* handle the security violation event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (dier & DIER_SVIE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (dsr & DSR_SVF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * Disable the interrupt when this kind of event has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * happened.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * There cannot be more than one event of this type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * because it needs a complex state change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * including a main power cycle to get again out of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * this state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) di_int_disable(imxdi, DIER_SVIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /* report the violation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) di_report_tamper_info(imxdi, dsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) rc = IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) /* handle write complete and write error cases */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (dier & DIER_WCIE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /*If the write wait queue is empty then there is no pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) operations. It means the interrupt is for DryIce -Security.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) IRQ must be returned as none.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (list_empty_careful(&imxdi->write_wait.head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /* DSR_WCF clears itself on DSR read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (dsr & (DSR_WCF | DSR_WEF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /* mask the interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) di_int_disable(imxdi, DIER_WCIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /* save the dsr value for the wait queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) imxdi->dsr |= dsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) wake_up_interruptible(&imxdi->write_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) rc = IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) /* handle the alarm case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (dier & DIER_CAIE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /* DSR_WCF clears itself on DSR read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (dsr & DSR_CAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /* mask the interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) di_int_disable(imxdi, DIER_CAIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) /* finish alarm in user context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) schedule_work(&imxdi->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) rc = IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * post the alarm event from user context so it can sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * on the write completion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) static void dryice_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) struct imxdi_dev *imxdi = container_of(work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) struct imxdi_dev, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* dismiss the interrupt (ignore error) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) di_write_wait(imxdi, DSR_CAF, DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* pass the alarm event to the rtc framework. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) rtc_update_irq(imxdi->rtc, 1, RTC_AF | RTC_IRQF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * probe for dryice rtc device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) static int __init dryice_rtc_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) struct imxdi_dev *imxdi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) int norm_irq, sec_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (!imxdi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) imxdi->pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) imxdi->ioaddr = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (IS_ERR(imxdi->ioaddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return PTR_ERR(imxdi->ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) spin_lock_init(&imxdi->irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) norm_irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (norm_irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return norm_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) /* the 2nd irq is the security violation irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) * make this optional, don't break the device tree ABI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) sec_irq = platform_get_irq(pdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (sec_irq <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) sec_irq = IRQ_NOTCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) init_waitqueue_head(&imxdi->write_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) INIT_WORK(&imxdi->work, dryice_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) mutex_init(&imxdi->write_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) imxdi->rtc = devm_rtc_allocate_device(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (IS_ERR(imxdi->rtc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return PTR_ERR(imxdi->rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) imxdi->clk = devm_clk_get(&pdev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (IS_ERR(imxdi->clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return PTR_ERR(imxdi->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) rc = clk_prepare_enable(imxdi->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * Initialize dryice hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /* mask all interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) writel(0, imxdi->ioaddr + DIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) rc = di_handle_state(imxdi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) rc = devm_request_irq(&pdev->dev, norm_irq, dryice_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) IRQF_SHARED, pdev->name, imxdi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) dev_warn(&pdev->dev, "interrupt not available.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) rc = devm_request_irq(&pdev->dev, sec_irq, dryice_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) IRQF_SHARED, pdev->name, imxdi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) dev_warn(&pdev->dev, "security violation interrupt not available.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) /* this is not an error, see above */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) platform_set_drvdata(pdev, imxdi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) imxdi->rtc->ops = &dryice_rtc_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) imxdi->rtc->range_max = U32_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) rc = rtc_register_device(imxdi->rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) clk_disable_unprepare(imxdi->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) static int __exit dryice_rtc_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) struct imxdi_dev *imxdi = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) flush_work(&imxdi->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* mask all interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) writel(0, imxdi->ioaddr + DIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) clk_disable_unprepare(imxdi->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static const struct of_device_id dryice_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) { .compatible = "fsl,imx25-rtc" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) MODULE_DEVICE_TABLE(of, dryice_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) static struct platform_driver dryice_rtc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) .name = "imxdi_rtc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .of_match_table = of_match_ptr(dryice_dt_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) .remove = __exit_p(dryice_rtc_remove),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) module_platform_driver_probe(dryice_rtc_driver, dryice_rtc_probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) MODULE_AUTHOR("Freescale Semiconductor, Inc.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) MODULE_DESCRIPTION("IMX DryIce Realtime Clock Driver (RTC)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) MODULE_LICENSE("GPL");