diff --git a/Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml b/Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml index f0581393dbcd9b..16da929e83d9de 100644 --- a/Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml @@ -33,6 +33,11 @@ properties: PMU alarm compare value, a 32-bit count of whole seconds of the RTC counter without the offset. - description: PMU alarm mask byte. + - description: + PMU alarm event byte, write 1 to clear. Maverick PMUs, such as the + M1 Pro's and the M2 Pro's, latch a fired alarm here as well as in the + control byte, and keep the alarm interrupt silent until it is + cleared. nvmem-cell-names: oneOf: @@ -43,11 +48,17 @@ properties: - const: rtc_ctrl - const: rtc_alarm - const: rtc_alarm_mask + - items: + - const: rtc_offset + - const: rtc_ctrl + - const: rtc_alarm + - const: rtc_alarm_mask + - const: rtc_alarm_event interrupts: maxItems: 1 description: - The PMU's RTC alarm interrupt. Only used with the three alarm cells. + The PMU's RTC alarm interrupt. Only used with the alarm cells. wakeup-source: true diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi index 008276bc52d67e..fa6680adaad63a 100644 --- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi +++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi @@ -301,8 +301,13 @@ rtc { compatible = "apple,smc-rtc"; - nvmem-cells = <&rtc_offset>; - nvmem-cell-names = "rtc_offset"; + nvmem-cells = <&rtc_offset>, <&rtc_ctrl>, <&rtc_alarm>, + <&rtc_alarm_mask>, <&rtc_alarm_event>; + nvmem-cell-names = "rtc_offset", "rtc_ctrl", "rtc_alarm", + "rtc_alarm_mask", "rtc_alarm_event"; + /* The PMU's RTC alarm, peripheral interrupt 2 of nub-spmi0 */ + interrupts-extended = <&nub_spmi0 2 IRQ_TYPE_EDGE_RISING>; + wakeup-source; }; }; @@ -345,6 +350,10 @@ reg = <0x2 0x920a1300 0x0 0x100>; #address-cells = <2>; #size-cells = <0>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&aic>; + interrupts = ; pmic1: pmic@f { compatible = "apple,maverick-pmic", "apple,spmi-nvmem"; @@ -355,14 +364,30 @@ #address-cells = <1>; #size-cells = <1>; + rtc_ctrl: rtc-ctrl@1401 { + reg = <0x1401 0x1>; + }; + pm_setting: pm-setting@1405 { reg = <0x1405 0x1>; }; + rtc_alarm: rtc-alarm@140c { + reg = <0x140c 0x4>; + }; + rtc_offset: rtc-offset@1411 { reg = <0x1411 0x6>; }; + rtc_alarm_event: rtc-alarm-event@14c0 { + reg = <0x14c0 0x1>; + }; + + rtc_alarm_mask: rtc-alarm-mask@14c2 { + reg = <0x14c2 0x1>; + }; + boot_stage: boot-stage@6001 { reg = <0x6001 0x1>; }; diff --git a/drivers/rtc/rtc-macsmc.c b/drivers/rtc/rtc-macsmc.c index aed6940cc61c09..9cc0709e1220e0 100644 --- a/drivers/rtc/rtc-macsmc.c +++ b/drivers/rtc/rtc-macsmc.c @@ -35,6 +35,17 @@ #define RTC_CTRL_ALARM_EVENT BIT(1) #define RTC_CTRL_ALARM_EN BIT(6) +/* + * The time comes from the SMC's CLKM, which lags the PMU's counter, the + * alarm's comparator, by a few ms (5.8 ms on J314s). With a tick offset whose + * fraction is smaller than that, the alarm would fire while the time still + * reads the second before. The RTC core then sets the same second again, the + * alarm fires again at once, and so on until the time catches up: five or six + * interrupts instead of one. So below this margin the alarm is armed one counter + * second later, and fires within the set second. + */ +#define RTC_ALARM_MARGIN_TICKS (1 << (RTC_SEC_SHIFT - 5)) /* 1/32 s */ + struct macsmc_rtc { struct device *dev; struct apple_smc *smc; @@ -45,6 +56,12 @@ struct macsmc_rtc { struct nvmem_cell *alarm_ctrl; struct nvmem_cell *alarm_value; struct nvmem_cell *alarm_mask; + /* + * Maverick PMUs (the M1 Pro's and the M2 Pro's) also latch the event in + * a separate, write-1-to-clear interrupt status register, and their + * control byte's event bit clears when it is written as 0, not as 1. + */ + struct nvmem_cell *alarm_event; struct mutex alarm_lock; u32 alarm_secs; }; @@ -174,8 +191,12 @@ static int macsmc_rtc_write_u8(struct nvmem_cell *cell, u8 val) return ret < 0 ? ret : 0; } -/* The wall-clock offset in whole seconds: wall time = counter seconds + offset */ -static int macsmc_rtc_offset_secs(struct macsmc_rtc *rtc, s64 *secs) +/* + * The wall-clock offset in whole seconds (wall time = counter seconds + offset), + * and the counter seconds to add to an alarm for RTC_ALARM_MARGIN_TICKS: 1 with + * a tick offset whose fraction is under the margin, else 0. + */ +static int macsmc_rtc_offset_secs(struct macsmc_rtc *rtc, s64 *secs, int *late) { u64 off = 0; size_t len; @@ -191,6 +212,7 @@ static int macsmc_rtc_offset_secs(struct macsmc_rtc *rtc, s64 *secs) return -EIO; } *secs = (s64)get_unaligned_le64(p); + *late = 0; } else { if (len < RTC_BYTES) { kfree(p); @@ -198,6 +220,7 @@ static int macsmc_rtc_offset_secs(struct macsmc_rtc *rtc, s64 *secs) } memcpy(&off, p, RTC_BYTES); *secs = sign_extend64(off, RTC_BITS - 1) >> RTC_SEC_SHIFT; + *late = (off & ((1 << RTC_SEC_SHIFT) - 1)) < RTC_ALARM_MARGIN_TICKS; } kfree(p); @@ -206,8 +229,11 @@ static int macsmc_rtc_offset_secs(struct macsmc_rtc *rtc, s64 *secs) /* * Arm the alarm at counter second @secs, or disarm it if @secs is 0. The - * other bits of the control byte are kept. A latched event is cleared by - * writing it back, so the event bit is written as 1 only to clear it. + * other bits of the control byte are kept. A latched event is cleared first: + * on T6030 by writing the control byte back with the event bit set; on a + * Maverick PMU by writing 1 to its interrupt status, which must be clear for + * the next alarm to raise an interrupt, while the control byte's event bit + * clears below, where it is written as 0. */ static int macsmc_rtc_program_alarm(struct macsmc_rtc *rtc, u32 secs) { @@ -218,7 +244,11 @@ static int macsmc_rtc_program_alarm(struct macsmc_rtc *rtc, u32 secs) ret = macsmc_rtc_read_u8(rtc->alarm_ctrl, &ctrl); if (ret) return ret; - if (ctrl & RTC_CTRL_ALARM_EVENT) { + if (rtc->alarm_event) { + ret = macsmc_rtc_write_u8(rtc->alarm_event, 1); + if (ret) + return ret; + } else if (ctrl & RTC_CTRL_ALARM_EVENT) { ret = macsmc_rtc_write_u8(rtc->alarm_ctrl, ctrl); if (ret) return ret; @@ -250,11 +280,12 @@ static int macsmc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) size_t len; s64 off; u32 secs; + int late; void *p; u8 ctrl; int ret; - ret = macsmc_rtc_offset_secs(rtc, &off); + ret = macsmc_rtc_offset_secs(rtc, &off, &late); if (ret) return ret; @@ -270,7 +301,8 @@ static int macsmc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) secs = len >= sizeof(u32) ? get_unaligned_le32(p) : 0; kfree(p); - rtc_time64_to_tm((time64_t)secs + off, &alrm->time); + /* The time that was set, not the counter second it was armed for */ + rtc_time64_to_tm((time64_t)secs - late + off, &alrm->time); alrm->enabled = !!(ctrl & RTC_CTRL_ALARM_EN); alrm->pending = !!(ctrl & RTC_CTRL_ALARM_EVENT); out: @@ -282,18 +314,21 @@ static int macsmc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct macsmc_rtc *rtc = dev_get_drvdata(dev); s64 off, secs; + int late; int ret; - ret = macsmc_rtc_offset_secs(rtc, &off); + ret = macsmc_rtc_offset_secs(rtc, &off, &late); if (ret) return ret; /* * With a tick offset, off is rounded down to whole seconds but the * time is floor((ctr + off) / 2^15), so the alarm fires at the set - * second or up to one second after it. + * second or up to one second after it. With the offset's fraction + * under RTC_ALARM_MARGIN_TICKS, the alarm is armed a second later, so + * it can't fire while the time still reads the second before. */ - secs = rtc_tm_to_time64(&alrm->time) - off; + secs = rtc_tm_to_time64(&alrm->time) - off + late; if (secs <= 0 || secs > U32_MAX) return -ERANGE; @@ -366,12 +401,15 @@ static int macsmc_rtc_init_alarm(struct platform_device *pdev, rtc->alarm_ctrl = macsmc_rtc_cell_optional(dev, "rtc_ctrl"); rtc->alarm_value = macsmc_rtc_cell_optional(dev, "rtc_alarm"); rtc->alarm_mask = macsmc_rtc_cell_optional(dev, "rtc_alarm_mask"); + rtc->alarm_event = macsmc_rtc_cell_optional(dev, "rtc_alarm_event"); if (IS_ERR(rtc->alarm_ctrl)) return PTR_ERR(rtc->alarm_ctrl); if (IS_ERR(rtc->alarm_value)) return PTR_ERR(rtc->alarm_value); if (IS_ERR(rtc->alarm_mask)) return PTR_ERR(rtc->alarm_mask); + if (IS_ERR(rtc->alarm_event)) + return PTR_ERR(rtc->alarm_event); if (!rtc->alarm_ctrl || !rtc->alarm_value || !rtc->alarm_mask) return -ENODEV; diff --git a/drivers/spmi/spmi-apple-controller.c b/drivers/spmi/spmi-apple-controller.c index 1cfaecdce65efd..d32dd3f7fb19ce 100644 --- a/drivers/spmi/spmi-apple-controller.c +++ b/drivers/spmi/spmi-apple-controller.c @@ -34,10 +34,13 @@ #define SPMI_IRQ_MASK_BASE 0x20 #define SPMI_IRQ_ACK_BASE 0x60 +/* + * Peripheral interrupts come first, up to 256 of them depending on the SoC + * (apple_spmi_hw.peripheral_irqs); the controller's own 32 events follow, the + * first being "notify", the RX FIFO no longer empty. + */ #define SPMI_NUM_PERIPHERAL_IRQS 256 -#define SPMI_NUM_IRQS (SPMI_NUM_PERIPHERAL_IRQS + 32) - -#define SPMI_IRQ_NOTIFY 256 +#define SPMI_NUM_CTRL_IRQS 32 /* SPMI_RSP_REG reply word */ #define SPMI_REPLY_FRAME_PARITY_STATUS GENMASK(31, 16) @@ -57,6 +60,7 @@ struct apple_spmi_hw { u32 reply; u32 rx_empty; bool legacy_irqs; + u32 peripheral_irqs; }; static const struct apple_spmi_hw apple_spmi_gen1 = { @@ -65,6 +69,20 @@ static const struct apple_spmi_hw apple_spmi_gen1 = { .reply = SPMI_RSP_REG, .rx_empty = SPMI_RX_FIFO_EMPTY, .legacy_irqs = true, + .peripheral_irqs = 256, +}; + +/* + * As gen1, but with 192 peripheral interrupts: macOS's nub-spmi0 numbers its + * events from 0xc0, and with a reply waiting the pending bit is 192. + */ +static const struct apple_spmi_hw apple_spmi_t6000 = { + .status = SPMI_STATUS_REG, + .command = SPMI_CMD_REG, + .reply = SPMI_RSP_REG, + .rx_empty = SPMI_RX_FIFO_EMPTY, + .legacy_irqs = true, + .peripheral_irqs = 192, }; static const struct apple_spmi_hw apple_spmi_gen4 = { @@ -87,6 +105,17 @@ struct apple_spmi { bool prev_fail; }; +static u32 apple_spmi_notify(struct apple_spmi *spmi) +{ + return spmi->hw->peripheral_irqs; +} + +/* 32-bit mask (and ack) words for the peripheral interrupts and the events */ +static size_t apple_spmi_irq_words(struct apple_spmi *spmi) +{ + return (spmi->hw->peripheral_irqs + SPMI_NUM_CTRL_IRQS) / 32; +} + static void apple_spmi_irq_ack_raw(struct apple_spmi *spmi, u32 irq) { u32 __iomem *reg = spmi->regs + SPMI_IRQ_ACK_BASE + (irq / 32) * 4; @@ -190,7 +219,7 @@ static int spmi_raw_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, u16 param, if (!spmi->hw->legacy_irqs) return -EIO; writel(SPMI_ACT_FIFO_FLUSH, spmi->regs + SPMI_ACT_REG); - apple_spmi_irq_ack_raw(spmi, SPMI_IRQ_NOTIFY); + apple_spmi_irq_ack_raw(spmi, apple_spmi_notify(spmi)); spmi->prev_fail = false; } reinit_completion(&spmi->fifo_rx); @@ -329,12 +358,13 @@ static int apple_spmi_irq_domain_translate(struct irq_domain *irqd, unsigned long *hwirq, unsigned int *type) { + struct apple_spmi *spmi = irqd->host_data; u32 *args = fwspec->param; if (fwspec->param_count != 2) return -EINVAL; - if (args[0] >= SPMI_NUM_PERIPHERAL_IRQS) + if (args[0] >= spmi->hw->peripheral_irqs) return -EINVAL; *hwirq = args[0]; *type = args[1] & IRQ_TYPE_SENSE_MASK; @@ -344,6 +374,7 @@ static int apple_spmi_irq_domain_translate(struct irq_domain *irqd, static int apple_spmi_irq_domain_alloc(struct irq_domain *irqd, unsigned int virq, unsigned int nr_irqs, void *arg) { + struct apple_spmi *spmi = irqd->host_data; unsigned int type = IRQ_TYPE_NONE; struct irq_fwspec *fwspec = arg; irq_hw_number_t hwirq; @@ -353,7 +384,7 @@ static int apple_spmi_irq_domain_alloc(struct irq_domain *irqd, unsigned int vir if (ret) return ret; - if (hwirq + nr_irqs > SPMI_NUM_PERIPHERAL_IRQS) + if (hwirq + nr_irqs > spmi->hw->peripheral_irqs) return -EINVAL; for (i = 0; i < nr_irqs; i++) { @@ -392,14 +423,14 @@ static void apple_spmi_irq_handler(struct irq_desc *desc) unsigned long val, offset, bit; chained_irq_enter(chip, desc); - val = readl(spmi->regs + SPMI_IRQ_ACK_BASE + (SPMI_IRQ_NOTIFY / 32) * 4); - if (val & BIT(SPMI_IRQ_NOTIFY % 32)) { - apple_spmi_irq_ack_raw(spmi, SPMI_IRQ_NOTIFY); + val = readl(spmi->regs + SPMI_IRQ_ACK_BASE + (apple_spmi_notify(spmi) / 32) * 4); + if (val & BIT(apple_spmi_notify(spmi) % 32)) { + apple_spmi_irq_ack_raw(spmi, apple_spmi_notify(spmi)); complete(&spmi->fifo_rx); handled = true; } - for (offset = 0; offset < SPMI_NUM_PERIPHERAL_IRQS / 8; offset += sizeof(val)) { + for (offset = 0; offset < spmi->hw->peripheral_irqs / 8; offset += sizeof(val)) { val = readq(spmi->regs + SPMI_IRQ_ACK_BASE + offset); /** * because of other masters in the bus, we're going to get a multitude of @@ -422,7 +453,7 @@ static void apple_spmi_teardown_irq(void *data) { struct apple_spmi *spmi = data; - for (size_t offset = 0; offset < SPMI_NUM_IRQS / 8; offset += 4) + for (size_t offset = 0; offset < apple_spmi_irq_words(spmi) * 4; offset += 4) writel(0, spmi->regs + SPMI_IRQ_MASK_BASE + offset); synchronize_irq(spmi->irq); @@ -442,7 +473,7 @@ static int apple_spmi_init_irq(struct platform_device *pdev, raw_spin_lock_init(&spmi->irq_mask_lock); - for (size_t offset = 0; offset < SPMI_NUM_IRQS / 8; offset += 4) { + for (size_t offset = 0; offset < apple_spmi_irq_words(spmi) * 4; offset += 4) { writel(0, spmi->regs + SPMI_IRQ_MASK_BASE + offset); writel(U32_MAX, spmi->regs + SPMI_IRQ_ACK_BASE + offset); } @@ -456,7 +487,7 @@ static int apple_spmi_init_irq(struct platform_device *pdev, return ret; irq_set_chained_handler_and_data(spmi->irq, apple_spmi_irq_handler, spmi); - apple_spmi_irq_unmask_raw(spmi, SPMI_IRQ_NOTIFY); + apple_spmi_irq_unmask_raw(spmi, apple_spmi_notify(spmi)); spmi->notify_irq = true; return 0; @@ -512,6 +543,7 @@ static int apple_spmi_probe(struct platform_device *pdev) static const struct of_device_id apple_spmi_match_table[] = { { .compatible = "apple,t8142-spmi", .data = &apple_spmi_gen4 }, + { .compatible = "apple,t6000-spmi", .data = &apple_spmi_t6000 }, { .compatible = "apple,t8103-spmi", .data = &apple_spmi_gen1 }, { .compatible = "apple,spmi", .data = &apple_spmi_gen1 }, {}