^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * DB8500 PRCM Unit driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) STMicroelectronics 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) ST-Ericsson SA 2010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Author: Sundar Iyer <sundar.iyer@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * U8500 PRCM Unit interface driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/mfd/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/mfd/dbx500-prcmu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/mfd/abx500/ab8500.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/regulator/db8500-prcmu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/regulator/machine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/platform_data/ux500_wdt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include "dbx500-prcmu-regs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* Index of different voltages to be used when accessing AVSData */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define PRCM_AVS_BASE 0x2FC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define PRCM_AVS_VBB_MAX_OPP (PRCM_AVS_BASE + 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define PRCM_AVS_VBB_100_OPP (PRCM_AVS_BASE + 0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define PRCM_AVS_VBB_50_OPP (PRCM_AVS_BASE + 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define PRCM_AVS_VARM_MAX_OPP (PRCM_AVS_BASE + 0x4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define PRCM_AVS_VARM_100_OPP (PRCM_AVS_BASE + 0x5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define PRCM_AVS_VARM_50_OPP (PRCM_AVS_BASE + 0x6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define PRCM_AVS_VARM_RET (PRCM_AVS_BASE + 0x7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define PRCM_AVS_VAPE_100_OPP (PRCM_AVS_BASE + 0x8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define PRCM_AVS_VAPE_50_OPP (PRCM_AVS_BASE + 0x9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define PRCM_AVS_VMOD_100_OPP (PRCM_AVS_BASE + 0xA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define PRCM_AVS_VMOD_50_OPP (PRCM_AVS_BASE + 0xB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define PRCM_AVS_VSAFE (PRCM_AVS_BASE + 0xC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define PRCM_AVS_VOLTAGE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define PRCM_AVS_VOLTAGE_MASK 0x3f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define PRCM_AVS_ISSLOWSTARTUP 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define PRCM_AVS_ISSLOWSTARTUP_MASK (1 << PRCM_AVS_ISSLOWSTARTUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define PRCM_AVS_ISMODEENABLE 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define PRCM_AVS_ISMODEENABLE_MASK (1 << PRCM_AVS_ISMODEENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define PRCM_BOOT_STATUS 0xFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define PRCM_ROMCODE_A2P 0xFFE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define PRCM_ROMCODE_P2A 0xFFD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define PRCM_XP70_CUR_PWR_STATE 0xFFC /* 4 BYTES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define PRCM_SW_RST_REASON 0xFF8 /* 2 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define _PRCM_MBOX_HEADER 0xFE8 /* 16 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define PRCM_MBOX_HEADER_REQ_MB0 (_PRCM_MBOX_HEADER + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define PRCM_MBOX_HEADER_REQ_MB1 (_PRCM_MBOX_HEADER + 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define PRCM_MBOX_HEADER_REQ_MB2 (_PRCM_MBOX_HEADER + 0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define PRCM_MBOX_HEADER_REQ_MB3 (_PRCM_MBOX_HEADER + 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define PRCM_MBOX_HEADER_REQ_MB4 (_PRCM_MBOX_HEADER + 0x4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define PRCM_MBOX_HEADER_REQ_MB5 (_PRCM_MBOX_HEADER + 0x5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define PRCM_MBOX_HEADER_ACK_MB0 (_PRCM_MBOX_HEADER + 0x8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* Req Mailboxes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define PRCM_REQ_MB0 0xFDC /* 12 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define PRCM_REQ_MB1 0xFD0 /* 12 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define PRCM_REQ_MB2 0xFC0 /* 16 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define PRCM_REQ_MB3 0xE4C /* 372 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define PRCM_REQ_MB4 0xE48 /* 4 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define PRCM_REQ_MB5 0xE44 /* 4 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* Ack Mailboxes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define PRCM_ACK_MB0 0xE08 /* 52 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define PRCM_ACK_MB1 0xE04 /* 4 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define PRCM_ACK_MB2 0xE00 /* 4 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define PRCM_ACK_MB3 0xDFC /* 4 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define PRCM_ACK_MB4 0xDF8 /* 4 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define PRCM_ACK_MB5 0xDF4 /* 4 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* Mailbox 0 headers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define MB0H_POWER_STATE_TRANS 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define MB0H_CONFIG_WAKEUPS_EXE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define MB0H_READ_WAKEUP_ACK 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define MB0H_CONFIG_WAKEUPS_SLEEP 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define MB0H_WAKEUP_EXE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define MB0H_WAKEUP_SLEEP 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* Mailbox 0 REQs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define PRCM_REQ_MB0_AP_POWER_STATE (PRCM_REQ_MB0 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define PRCM_REQ_MB0_AP_PLL_STATE (PRCM_REQ_MB0 + 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define PRCM_REQ_MB0_ULP_CLOCK_STATE (PRCM_REQ_MB0 + 0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define PRCM_REQ_MB0_DO_NOT_WFI (PRCM_REQ_MB0 + 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define PRCM_REQ_MB0_WAKEUP_8500 (PRCM_REQ_MB0 + 0x4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define PRCM_REQ_MB0_WAKEUP_4500 (PRCM_REQ_MB0 + 0x8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Mailbox 0 ACKs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define PRCM_ACK_MB0_AP_PWRSTTR_STATUS (PRCM_ACK_MB0 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define PRCM_ACK_MB0_READ_POINTER (PRCM_ACK_MB0 + 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define PRCM_ACK_MB0_WAKEUP_0_8500 (PRCM_ACK_MB0 + 0x4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define PRCM_ACK_MB0_WAKEUP_0_4500 (PRCM_ACK_MB0 + 0x8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define PRCM_ACK_MB0_WAKEUP_1_8500 (PRCM_ACK_MB0 + 0x1C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define PRCM_ACK_MB0_WAKEUP_1_4500 (PRCM_ACK_MB0 + 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define PRCM_ACK_MB0_EVENT_4500_NUMBERS 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* Mailbox 1 headers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define MB1H_ARM_APE_OPP 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define MB1H_RESET_MODEM 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define MB1H_REQUEST_APE_OPP_100_VOLT 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define MB1H_RELEASE_APE_OPP_100_VOLT 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define MB1H_RELEASE_USB_WAKEUP 0x5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define MB1H_PLL_ON_OFF 0x6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* Mailbox 1 Requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define PRCM_REQ_MB1_PLL_ON_OFF (PRCM_REQ_MB1 + 0x4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define PLL_SOC0_OFF 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define PLL_SOC0_ON 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define PLL_SOC1_OFF 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define PLL_SOC1_ON 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* Mailbox 1 ACKs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define PRCM_ACK_MB1_CURRENT_ARM_OPP (PRCM_ACK_MB1 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define PRCM_ACK_MB1_CURRENT_APE_OPP (PRCM_ACK_MB1 + 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define PRCM_ACK_MB1_APE_VOLTAGE_STATUS (PRCM_ACK_MB1 + 0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define PRCM_ACK_MB1_DVFS_STATUS (PRCM_ACK_MB1 + 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* Mailbox 2 headers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define MB2H_DPS 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define MB2H_AUTO_PWR 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* Mailbox 2 REQs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define PRCM_REQ_MB2_SVA_MMDSP (PRCM_REQ_MB2 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define PRCM_REQ_MB2_SVA_PIPE (PRCM_REQ_MB2 + 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define PRCM_REQ_MB2_SIA_MMDSP (PRCM_REQ_MB2 + 0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define PRCM_REQ_MB2_SIA_PIPE (PRCM_REQ_MB2 + 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define PRCM_REQ_MB2_SGA (PRCM_REQ_MB2 + 0x4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define PRCM_REQ_MB2_B2R2_MCDE (PRCM_REQ_MB2 + 0x5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define PRCM_REQ_MB2_ESRAM12 (PRCM_REQ_MB2 + 0x6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define PRCM_REQ_MB2_ESRAM34 (PRCM_REQ_MB2 + 0x7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define PRCM_REQ_MB2_AUTO_PM_SLEEP (PRCM_REQ_MB2 + 0x8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define PRCM_REQ_MB2_AUTO_PM_IDLE (PRCM_REQ_MB2 + 0xC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* Mailbox 2 ACKs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define PRCM_ACK_MB2_DPS_STATUS (PRCM_ACK_MB2 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define HWACC_PWR_ST_OK 0xFE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* Mailbox 3 headers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define MB3H_ANC 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define MB3H_SIDETONE 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define MB3H_SYSCLK 0xE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* Mailbox 3 Requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define PRCM_REQ_MB3_ANC_FIR_COEFF (PRCM_REQ_MB3 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define PRCM_REQ_MB3_ANC_IIR_COEFF (PRCM_REQ_MB3 + 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define PRCM_REQ_MB3_ANC_SHIFTER (PRCM_REQ_MB3 + 0x60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define PRCM_REQ_MB3_ANC_WARP (PRCM_REQ_MB3 + 0x64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define PRCM_REQ_MB3_SIDETONE_FIR_GAIN (PRCM_REQ_MB3 + 0x68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define PRCM_REQ_MB3_SIDETONE_FIR_COEFF (PRCM_REQ_MB3 + 0x6C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define PRCM_REQ_MB3_SYSCLK_MGT (PRCM_REQ_MB3 + 0x16C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* Mailbox 4 headers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define MB4H_DDR_INIT 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define MB4H_MEM_ST 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define MB4H_HOTDOG 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define MB4H_HOTMON 0x13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define MB4H_HOT_PERIOD 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define MB4H_A9WDOG_CONF 0x16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #define MB4H_A9WDOG_EN 0x17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #define MB4H_A9WDOG_DIS 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #define MB4H_A9WDOG_LOAD 0x19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #define MB4H_A9WDOG_KICK 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /* Mailbox 4 Requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE (PRCM_REQ_MB4 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #define PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE (PRCM_REQ_MB4 + 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #define PRCM_REQ_MB4_ESRAM0_ST (PRCM_REQ_MB4 + 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) #define PRCM_REQ_MB4_HOTDOG_THRESHOLD (PRCM_REQ_MB4 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #define PRCM_REQ_MB4_HOTMON_LOW (PRCM_REQ_MB4 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) #define PRCM_REQ_MB4_HOTMON_HIGH (PRCM_REQ_MB4 + 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #define PRCM_REQ_MB4_HOTMON_CONFIG (PRCM_REQ_MB4 + 0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #define PRCM_REQ_MB4_HOT_PERIOD (PRCM_REQ_MB4 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define HOTMON_CONFIG_LOW BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #define HOTMON_CONFIG_HIGH BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #define PRCM_REQ_MB4_A9WDOG_0 (PRCM_REQ_MB4 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #define PRCM_REQ_MB4_A9WDOG_1 (PRCM_REQ_MB4 + 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) #define PRCM_REQ_MB4_A9WDOG_2 (PRCM_REQ_MB4 + 0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #define PRCM_REQ_MB4_A9WDOG_3 (PRCM_REQ_MB4 + 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #define A9WDOG_AUTO_OFF_EN BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) #define A9WDOG_AUTO_OFF_DIS 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) #define A9WDOG_ID_MASK 0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* Mailbox 5 Requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) #define PRCM_REQ_MB5_I2C_SLAVE_OP (PRCM_REQ_MB5 + 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) #define PRCM_REQ_MB5_I2C_HW_BITS (PRCM_REQ_MB5 + 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) #define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) #define PRCM_REQ_MB5_I2C_VAL (PRCM_REQ_MB5 + 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) #define PRCMU_I2C_WRITE(slave) (((slave) << 1) | BIT(6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) #define PRCMU_I2C_READ(slave) (((slave) << 1) | BIT(0) | BIT(6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) #define PRCMU_I2C_STOP_EN BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* Mailbox 5 ACKs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) #define PRCM_ACK_MB5_I2C_STATUS (PRCM_ACK_MB5 + 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #define PRCM_ACK_MB5_I2C_VAL (PRCM_ACK_MB5 + 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #define I2C_WR_OK 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #define I2C_RD_OK 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #define NUM_MB 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #define MBOX_BIT BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) #define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * Wakeups/IRQs
^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) #define WAKEUP_BIT_RTC BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #define WAKEUP_BIT_RTT0 BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #define WAKEUP_BIT_RTT1 BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) #define WAKEUP_BIT_HSI0 BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) #define WAKEUP_BIT_HSI1 BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) #define WAKEUP_BIT_CA_WAKE BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #define WAKEUP_BIT_USB BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) #define WAKEUP_BIT_ABB BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #define WAKEUP_BIT_ABB_FIFO BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) #define WAKEUP_BIT_SYSCLK_OK BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #define WAKEUP_BIT_CA_SLEEP BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) #define WAKEUP_BIT_AC_WAKE_ACK BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) #define WAKEUP_BIT_SIDE_TONE_OK BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #define WAKEUP_BIT_ANC_OK BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) #define WAKEUP_BIT_SW_ERROR BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) #define WAKEUP_BIT_AC_SLEEP_ACK BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) #define WAKEUP_BIT_ARM BIT(17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) #define WAKEUP_BIT_HOTMON_LOW BIT(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) #define WAKEUP_BIT_HOTMON_HIGH BIT(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) #define WAKEUP_BIT_MODEM_SW_RESET_REQ BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) #define WAKEUP_BIT_GPIO0 BIT(23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) #define WAKEUP_BIT_GPIO1 BIT(24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) #define WAKEUP_BIT_GPIO2 BIT(25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) #define WAKEUP_BIT_GPIO3 BIT(26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) #define WAKEUP_BIT_GPIO4 BIT(27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) #define WAKEUP_BIT_GPIO5 BIT(28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) #define WAKEUP_BIT_GPIO6 BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) #define WAKEUP_BIT_GPIO7 BIT(30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) #define WAKEUP_BIT_GPIO8 BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) bool valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct prcmu_fw_version version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) } fw_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static struct irq_domain *db8500_irq_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * This vector maps irq numbers to the bits in the bit field used in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * communication with the PRCMU firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * The reason for having this is to keep the irq numbers contiguous even though
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * the bits in the bit field are not. (The bits also have a tendency to move
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * around, to further complicate matters.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) #define IRQ_INDEX(_name) ((IRQ_PRCMU_##_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) #define IRQ_ENTRY(_name)[IRQ_INDEX(_name)] = (WAKEUP_BIT_##_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) #define IRQ_PRCMU_RTC 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) #define IRQ_PRCMU_RTT0 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) #define IRQ_PRCMU_RTT1 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) #define IRQ_PRCMU_HSI0 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) #define IRQ_PRCMU_HSI1 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #define IRQ_PRCMU_CA_WAKE 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) #define IRQ_PRCMU_USB 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) #define IRQ_PRCMU_ABB 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) #define IRQ_PRCMU_ABB_FIFO 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) #define IRQ_PRCMU_ARM 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) #define IRQ_PRCMU_MODEM_SW_RESET_REQ 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) #define IRQ_PRCMU_GPIO0 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) #define IRQ_PRCMU_GPIO1 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) #define IRQ_PRCMU_GPIO2 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) #define IRQ_PRCMU_GPIO3 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) #define IRQ_PRCMU_GPIO4 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) #define IRQ_PRCMU_GPIO5 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) #define IRQ_PRCMU_GPIO6 17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) #define IRQ_PRCMU_GPIO7 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) #define IRQ_PRCMU_GPIO8 19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) #define IRQ_PRCMU_CA_SLEEP 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) #define IRQ_PRCMU_HOTMON_LOW 21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) #define IRQ_PRCMU_HOTMON_HIGH 22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) #define NUM_PRCMU_WAKEUPS 23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static u32 prcmu_irq_bit[NUM_PRCMU_WAKEUPS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) IRQ_ENTRY(RTC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) IRQ_ENTRY(RTT0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) IRQ_ENTRY(RTT1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) IRQ_ENTRY(HSI0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) IRQ_ENTRY(HSI1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) IRQ_ENTRY(CA_WAKE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) IRQ_ENTRY(USB),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) IRQ_ENTRY(ABB),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) IRQ_ENTRY(ABB_FIFO),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) IRQ_ENTRY(CA_SLEEP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) IRQ_ENTRY(ARM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) IRQ_ENTRY(HOTMON_LOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) IRQ_ENTRY(HOTMON_HIGH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) IRQ_ENTRY(MODEM_SW_RESET_REQ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) IRQ_ENTRY(GPIO0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) IRQ_ENTRY(GPIO1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) IRQ_ENTRY(GPIO2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) IRQ_ENTRY(GPIO3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) IRQ_ENTRY(GPIO4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) IRQ_ENTRY(GPIO5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) IRQ_ENTRY(GPIO6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) IRQ_ENTRY(GPIO7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) IRQ_ENTRY(GPIO8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) #define VALID_WAKEUPS (BIT(NUM_PRCMU_WAKEUP_INDICES) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) #define WAKEUP_ENTRY(_name)[PRCMU_WAKEUP_INDEX_##_name] = (WAKEUP_BIT_##_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static u32 prcmu_wakeup_bit[NUM_PRCMU_WAKEUP_INDICES] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) WAKEUP_ENTRY(RTC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) WAKEUP_ENTRY(RTT0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) WAKEUP_ENTRY(RTT1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) WAKEUP_ENTRY(HSI0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) WAKEUP_ENTRY(HSI1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) WAKEUP_ENTRY(USB),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) WAKEUP_ENTRY(ABB),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) WAKEUP_ENTRY(ABB_FIFO),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) WAKEUP_ENTRY(ARM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * mb0_transfer - state needed for mailbox 0 communication.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * @lock: The transaction lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * @dbb_events_lock: A lock used to handle concurrent access to (parts of)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * the request data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * @mask_work: Work structure used for (un)masking wakeup interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * @req: Request data that need to persist between requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) spinlock_t dbb_irqs_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct work_struct mask_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct mutex ac_wake_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct completion ac_wake_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) u32 dbb_irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) u32 dbb_wakeups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) u32 abb_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) } req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) } mb0_transfer;
^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) * mb1_transfer - state needed for mailbox 1 communication.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * @lock: The transaction lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * @work: The transaction completion structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * @ape_opp: The current APE OPP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * @ack: Reply ("acknowledge") data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct completion work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) u8 ape_opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) u8 header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) u8 arm_opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) u8 ape_opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) u8 ape_voltage_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) } ack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) } mb1_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * mb2_transfer - state needed for mailbox 2 communication.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * @lock: The transaction lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * @work: The transaction completion structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * @auto_pm_lock: The autonomous power management configuration lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * @auto_pm_enabled: A flag indicating whether autonomous PM is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * @req: Request data that need to persist between requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * @ack: Reply ("acknowledge") data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct completion work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) spinlock_t auto_pm_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) bool auto_pm_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) } ack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) } mb2_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * mb3_transfer - state needed for mailbox 3 communication.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * @lock: The request lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * @sysclk_lock: A lock used to handle concurrent sysclk requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * @sysclk_work: Work structure used for sysclk requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct mutex sysclk_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) struct completion sysclk_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) } mb3_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * mb4_transfer - state needed for mailbox 4 communication.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * @lock: The transaction lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * @work: The transaction completion structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct completion work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) } mb4_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * mb5_transfer - state needed for mailbox 5 communication.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * @lock: The transaction lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * @work: The transaction completion structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * @ack: Reply ("acknowledge") data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) struct completion work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) u8 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) } ack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) } mb5_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* Spinlocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) static DEFINE_SPINLOCK(prcmu_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static DEFINE_SPINLOCK(clkout_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) /* Global var to runtime determine TCDM base for v2 or v1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static __iomem void *tcdm_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static __iomem void *prcmu_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct clk_mgt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) u32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) u32 pllsw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) int branch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) bool clk38div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) PLL_RAW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) PLL_FIX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) PLL_DIV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static DEFINE_SPINLOCK(clk_mgt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) #define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) { (PRCM_##_name##_MGT), 0 , _branch, _clk38div}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) CLK_MGT_ENTRY(SGACLK, PLL_DIV, false),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) CLK_MGT_ENTRY(MSP02CLK, PLL_FIX, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) CLK_MGT_ENTRY(MSP1CLK, PLL_FIX, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) CLK_MGT_ENTRY(I2CCLK, PLL_FIX, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) CLK_MGT_ENTRY(SDMMCCLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) CLK_MGT_ENTRY(SLIMCLK, PLL_FIX, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) CLK_MGT_ENTRY(PER1CLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) CLK_MGT_ENTRY(PER2CLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) CLK_MGT_ENTRY(PER3CLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) CLK_MGT_ENTRY(PER5CLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) CLK_MGT_ENTRY(HDMICLK, PLL_FIX, false),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) CLK_MGT_ENTRY(APEATCLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) CLK_MGT_ENTRY(APETRACECLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) CLK_MGT_ENTRY(MCDECLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) CLK_MGT_ENTRY(IPI2CCLK, PLL_FIX, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) CLK_MGT_ENTRY(DSIALTCLK, PLL_FIX, false),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) CLK_MGT_ENTRY(DMACLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) CLK_MGT_ENTRY(B2R2CLK, PLL_DIV, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) CLK_MGT_ENTRY(TVCLK, PLL_FIX, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) CLK_MGT_ENTRY(SSPCLK, PLL_FIX, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) CLK_MGT_ENTRY(RNGCLK, PLL_FIX, true),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) CLK_MGT_ENTRY(UICCCLK, PLL_FIX, false),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct dsiclk {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) u32 divsel_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) u32 divsel_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) u32 divsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) static struct dsiclk dsiclk[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) .divsel = PRCM_DSI_PLLOUT_SEL_PHI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) .divsel = PRCM_DSI_PLLOUT_SEL_PHI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct dsiescclk {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) u32 en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) u32 div_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) u32 div_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) static struct dsiescclk dsiescclk[3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) .en = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) .div_mask = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) .div_shift = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) .en = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) .div_mask = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) .div_shift = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) .en = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) .div_mask = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) .div_shift = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) u32 db8500_prcmu_read(unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return readl(prcmu_base + reg);
^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) void db8500_prcmu_write(unsigned int reg, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) spin_lock_irqsave(&prcmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) writel(value, (prcmu_base + reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) spin_unlock_irqrestore(&prcmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) spin_lock_irqsave(&prcmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) val = readl(prcmu_base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) val = ((val & ~mask) | (value & mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) writel(val, (prcmu_base + reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) spin_unlock_irqrestore(&prcmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) struct prcmu_fw_version *prcmu_get_fw_version(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return fw_info.valid ? &fw_info.version : NULL;
^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) static bool prcmu_is_ulppll_disabled(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) struct prcmu_fw_version *ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) ver = prcmu_get_fw_version();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return ver && ver->project == PRCMU_FW_PROJECT_U8420_SYSCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) bool prcmu_has_arm_maxopp(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * prcmu_set_rc_a2p - This function is used to run few power state sequences
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * @val: Value to be set, i.e. transition requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * Returns: 0 on success, -EINVAL on invalid argument
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) * This function is used to run the following power state sequences -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) * any state to ApReset, ApDeepSleep to ApExecute, ApExecute to ApDeepSleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) int prcmu_set_rc_a2p(enum romcode_write val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (val < RDY_2_DS || val > RDY_2_XP70_RST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) writeb(val, (tcdm_base + PRCM_ROMCODE_A2P));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * prcmu_get_rc_p2a - This function is used to get power state sequences
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * Returns: the power transition that has last happened
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * This function can return the following transitions-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * any state to ApReset, ApDeepSleep to ApExecute, ApExecute to ApDeepSleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) enum romcode_read prcmu_get_rc_p2a(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) return readb(tcdm_base + PRCM_ROMCODE_P2A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * prcmu_get_current_mode - Return the current XP70 power mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * Returns: Returns the current AP(ARM) power mode: init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * apBoot, apExecute, apDeepSleep, apSleep, apIdle, apReset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) enum ap_pwrst prcmu_get_xp70_current_state(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return readb(tcdm_base + PRCM_XP70_CUR_PWR_STATE);
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * prcmu_config_clkout - Configure one of the programmable clock outputs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * @clkout: The CLKOUT number (0 or 1).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * @source: The clock to be used (one of the PRCMU_CLKSRC_*).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) * @div: The divider to be applied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * Configures one of the programmable clock outputs (CLKOUTs).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * @div should be in the range [1,63] to request a configuration, or 0 to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * inform that the configuration is no longer requested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static int requests[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) int r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) u32 bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) u32 div_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) BUG_ON(clkout > 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) BUG_ON(div > 63);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) BUG_ON((clkout == 0) && (source > PRCMU_CLKSRC_CLK009));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (!div && !requests[clkout])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (clkout == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) div_mask = PRCM_CLKOCR_CLKODIV0_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) mask = (PRCM_CLKOCR_CLKODIV0_MASK | PRCM_CLKOCR_CLKOSEL0_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) bits = ((source << PRCM_CLKOCR_CLKOSEL0_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) (div << PRCM_CLKOCR_CLKODIV0_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) div_mask = PRCM_CLKOCR_CLKODIV1_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) mask = (PRCM_CLKOCR_CLKODIV1_MASK | PRCM_CLKOCR_CLKOSEL1_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) PRCM_CLKOCR_CLK1TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) bits = ((source << PRCM_CLKOCR_CLKOSEL1_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) (div << PRCM_CLKOCR_CLKODIV1_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) bits &= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) spin_lock_irqsave(&clkout_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) val = readl(PRCM_CLKOCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (val & div_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (div) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if ((val & mask) != bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) r = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if ((val & mask & ~div_mask) != bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) r = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^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) writel((bits | (val & ~mask)), PRCM_CLKOCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) requests[clkout] += (div ? 1 : -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) unlock_and_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) spin_unlock_irqrestore(&clkout_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) BUG_ON((state < PRCMU_AP_SLEEP) || (PRCMU_AP_DEEP_IDLE < state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) spin_lock_irqsave(&mb0_transfer.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) writeb(MB0H_POWER_STATE_TRANS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) writeb(state, (tcdm_base + PRCM_REQ_MB0_AP_POWER_STATE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) writeb((keep_ap_pll ? 1 : 0), (tcdm_base + PRCM_REQ_MB0_AP_PLL_STATE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) writeb((keep_ulp_clk ? 1 : 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) (tcdm_base + PRCM_REQ_MB0_ULP_CLOCK_STATE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) writeb(0, (tcdm_base + PRCM_REQ_MB0_DO_NOT_WFI));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) spin_unlock_irqrestore(&mb0_transfer.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) u8 db8500_prcmu_get_power_state_result(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return readb(tcdm_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS);
^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) /* This function should only be called while mb0_transfer.lock is held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) static void config_wakeups(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) const u8 header[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) MB0H_CONFIG_WAKEUPS_EXE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) MB0H_CONFIG_WAKEUPS_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) static u32 last_dbb_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) static u32 last_abb_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) u32 dbb_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) u32 abb_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) dbb_events = mb0_transfer.req.dbb_irqs | mb0_transfer.req.dbb_wakeups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) dbb_events |= (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) abb_events = mb0_transfer.req.abb_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if ((dbb_events == last_dbb_events) && (abb_events == last_abb_events))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) writel(dbb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_8500));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) writel(abb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_4500));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) writeb(header[i], (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) last_dbb_events = dbb_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) last_abb_events = abb_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) void db8500_prcmu_enable_wakeups(u32 wakeups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) u32 bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) BUG_ON(wakeups != (wakeups & VALID_WAKEUPS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) for (i = 0, bits = 0; i < NUM_PRCMU_WAKEUP_INDICES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (wakeups & BIT(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) bits |= prcmu_wakeup_bit[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) spin_lock_irqsave(&mb0_transfer.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) mb0_transfer.req.dbb_wakeups = bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) config_wakeups();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) spin_unlock_irqrestore(&mb0_transfer.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) void db8500_prcmu_config_abb_event_readout(u32 abb_events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) spin_lock_irqsave(&mb0_transfer.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) mb0_transfer.req.abb_events = abb_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) config_wakeups();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) spin_unlock_irqrestore(&mb0_transfer.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) void db8500_prcmu_get_abb_event_buffer(void __iomem **buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) *buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_1_4500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) *buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_0_4500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * db8500_prcmu_set_arm_opp - set the appropriate ARM OPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * @opp: The new ARM operating point to which transition is to be made
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * Returns: 0 on success, non-zero on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * This function sets the the operating point of the ARM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) int db8500_prcmu_set_arm_opp(u8 opp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (opp < ARM_NO_CHANGE || opp > ARM_EXTCLK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) mutex_lock(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) writeb(opp, (tcdm_base + PRCM_REQ_MB1_ARM_OPP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) writeb(APE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_APE_OPP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) wait_for_completion(&mb1_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) (mb1_transfer.ack.arm_opp != opp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) r = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) mutex_unlock(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * db8500_prcmu_get_arm_opp - get the current ARM OPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) * Returns: the current ARM OPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) int db8500_prcmu_get_arm_opp(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * db8500_prcmu_get_ddr_opp - get the current DDR OPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * Returns: the current DDR OPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) int db8500_prcmu_get_ddr_opp(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return readb(PRCM_DDR_SUBSYS_APE_MINBW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) /* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static void request_even_slower_clocks(bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) u32 clock_reg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) PRCM_ACLK_MGT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) PRCM_DMACLK_MGT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) spin_lock_irqsave(&clk_mgt_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) /* Grab the HW semaphore. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) for (i = 0; i < ARRAY_SIZE(clock_reg); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) u32 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) val = readl(prcmu_base + clock_reg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) div = (val & PRCM_CLK_MGT_CLKPLLDIV_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) if ((div <= 1) || (div > 15)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) pr_err("prcmu: Bad clock divider %d in %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) div, __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) div <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (div <= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) div >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) val = ((val & ~PRCM_CLK_MGT_CLKPLLDIV_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) (div & PRCM_CLK_MGT_CLKPLLDIV_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) writel(val, prcmu_base + clock_reg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) unlock_and_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /* Release the HW semaphore. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) writel(0, PRCM_SEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) spin_unlock_irqrestore(&clk_mgt_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * db8500_set_ape_opp - set the appropriate APE OPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * @opp: The new APE operating point to which transition is to be made
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * Returns: 0 on success, non-zero on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) * This function sets the operating point of the APE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) int db8500_prcmu_set_ape_opp(u8 opp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) int r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (opp == mb1_transfer.ape_opp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) mutex_lock(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) request_even_slower_clocks(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if ((opp != APE_100_OPP) && (mb1_transfer.ape_opp != APE_100_OPP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) goto skip_message;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) writeb(((opp == APE_50_PARTLY_25_OPP) ? APE_50_OPP : opp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) (tcdm_base + PRCM_REQ_MB1_APE_OPP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) wait_for_completion(&mb1_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) (mb1_transfer.ack.ape_opp != opp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) r = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) skip_message:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if ((!r && (opp == APE_50_PARTLY_25_OPP)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) (r && (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) request_even_slower_clocks(true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (!r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) mb1_transfer.ape_opp = opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) mutex_unlock(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) * db8500_prcmu_get_ape_opp - get the current APE OPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) * Returns: the current APE OPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) int db8500_prcmu_get_ape_opp(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) * db8500_prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) * @enable: true to request the higher voltage, false to drop a request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * Calls to this function to enable and disable requests must be balanced.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) int r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) u8 header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) static unsigned int requests;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) mutex_lock(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (0 != requests++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) header = MB1H_REQUEST_APE_OPP_100_VOLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (requests == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) r = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) } else if (1 != requests--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) header = MB1H_RELEASE_APE_OPP_100_VOLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) writeb(header, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) wait_for_completion(&mb1_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if ((mb1_transfer.ack.header != header) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) ((mb1_transfer.ack.ape_voltage_status & BIT(0)) != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) r = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) unlock_and_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) mutex_unlock(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * prcmu_release_usb_wakeup_state - release the state required by a USB wakeup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * This function releases the power state requirements of a USB wakeup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) int prcmu_release_usb_wakeup_state(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) int r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) mutex_lock(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) writeb(MB1H_RELEASE_USB_WAKEUP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) wait_for_completion(&mb1_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if ((mb1_transfer.ack.header != MB1H_RELEASE_USB_WAKEUP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) ((mb1_transfer.ack.ape_voltage_status & BIT(0)) != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) r = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) mutex_unlock(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) static int request_pll(u8 clock, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) int r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (clock == PRCMU_PLLSOC0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) clock = (enable ? PLL_SOC0_ON : PLL_SOC0_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) else if (clock == PRCMU_PLLSOC1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) mutex_lock(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) writeb(MB1H_PLL_ON_OFF, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) writeb(clock, (tcdm_base + PRCM_REQ_MB1_PLL_ON_OFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) wait_for_completion(&mb1_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (mb1_transfer.ack.header != MB1H_PLL_ON_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) r = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) mutex_unlock(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) * db8500_prcmu_set_epod - set the state of a EPOD (power domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) * @epod_id: The EPOD to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) * @epod_state: The new EPOD state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) * This function sets the state of a EPOD (power domain). It may not be called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) * from interrupt context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) int r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) bool ram_retention = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /* check argument */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) BUG_ON(epod_id >= NUM_EPOD_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) /* set flag if retention is possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) switch (epod_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) case EPOD_ID_SVAMMDSP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) case EPOD_ID_SIAMMDSP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) case EPOD_ID_ESRAM12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) case EPOD_ID_ESRAM34:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) ram_retention = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) /* check argument */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) BUG_ON(epod_state > EPOD_STATE_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) BUG_ON(epod_state == EPOD_STATE_RAMRET && !ram_retention);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) /* get lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) mutex_lock(&mb2_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) /* wait for mailbox */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) /* fill in mailbox */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) for (i = 0; i < NUM_EPOD_ID; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) writeb(EPOD_STATE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB2 + i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) writeb(epod_state, (tcdm_base + PRCM_REQ_MB2 + epod_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) writeb(MB2H_DPS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) writel(MBOX_BIT(2), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) * The current firmware version does not handle errors correctly,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * and we cannot recover if there is an error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) * This is expected to change when the firmware is updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (!wait_for_completion_timeout(&mb2_transfer.work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) msecs_to_jiffies(20000))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) r = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (mb2_transfer.ack.status != HWACC_PWR_ST_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) r = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) unlock_and_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) mutex_unlock(&mb2_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) * prcmu_configure_auto_pm - Configure autonomous power management.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) * @sleep: Configuration for ApSleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) * @idle: Configuration for ApIdle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) struct prcmu_auto_pm_config *idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) u32 sleep_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) u32 idle_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) BUG_ON((sleep == NULL) || (idle == NULL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) sleep_cfg = (sleep->sva_auto_pm_enable & 0xF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) sleep_cfg = ((sleep_cfg << 4) | (sleep->sia_auto_pm_enable & 0xF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) sleep_cfg = ((sleep_cfg << 8) | (sleep->sva_power_on & 0xFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) sleep_cfg = ((sleep_cfg << 8) | (sleep->sia_power_on & 0xFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) sleep_cfg = ((sleep_cfg << 4) | (sleep->sva_policy & 0xF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) sleep_cfg = ((sleep_cfg << 4) | (sleep->sia_policy & 0xF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) idle_cfg = (idle->sva_auto_pm_enable & 0xF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) idle_cfg = ((idle_cfg << 4) | (idle->sia_auto_pm_enable & 0xF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) idle_cfg = ((idle_cfg << 8) | (idle->sva_power_on & 0xFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) idle_cfg = ((idle_cfg << 8) | (idle->sia_power_on & 0xFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) idle_cfg = ((idle_cfg << 4) | (idle->sva_policy & 0xF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) idle_cfg = ((idle_cfg << 4) | (idle->sia_policy & 0xF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) spin_lock_irqsave(&mb2_transfer.auto_pm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) * The autonomous power management configuration is done through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) * fields in mailbox 2, but these fields are only used as shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) * variables - i.e. there is no need to send a message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) writel(sleep_cfg, (tcdm_base + PRCM_REQ_MB2_AUTO_PM_SLEEP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) writel(idle_cfg, (tcdm_base + PRCM_REQ_MB2_AUTO_PM_IDLE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) mb2_transfer.auto_pm_enabled =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) ((sleep->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) (sleep->sia_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) (idle->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) (idle->sia_auto_pm_enable == PRCMU_AUTO_PM_ON));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) spin_unlock_irqrestore(&mb2_transfer.auto_pm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) EXPORT_SYMBOL(prcmu_configure_auto_pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) bool prcmu_is_auto_pm_enabled(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) return mb2_transfer.auto_pm_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) static int request_sysclk(bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) mutex_lock(&mb3_transfer.sysclk_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) spin_lock_irqsave(&mb3_transfer.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) writeb((enable ? ON : OFF), (tcdm_base + PRCM_REQ_MB3_SYSCLK_MGT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) writeb(MB3H_SYSCLK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) writel(MBOX_BIT(3), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) spin_unlock_irqrestore(&mb3_transfer.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) * The firmware only sends an ACK if we want to enable the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) * SysClk, and it succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) if (enable && !wait_for_completion_timeout(&mb3_transfer.sysclk_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) msecs_to_jiffies(20000))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) r = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) mutex_unlock(&mb3_transfer.sysclk_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) static int request_timclk(bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * On the U8420_CLKSEL firmware, the ULP (Ultra Low Power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) * PLL is disabled so we cannot use doze mode, this will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) * stop the clock on this firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (prcmu_is_ulppll_disabled())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) if (!enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) val |= PRCM_TCR_STOP_TIMERS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) PRCM_TCR_DOZE_MODE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) PRCM_TCR_TENSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) writel(val, PRCM_TCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) static int request_clock(u8 clock, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) spin_lock_irqsave(&clk_mgt_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) /* Grab the HW semaphore. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) val = readl(prcmu_base + clk_mgt[clock].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) writel(val, prcmu_base + clk_mgt[clock].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) /* Release the HW semaphore. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) writel(0, PRCM_SEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) spin_unlock_irqrestore(&clk_mgt_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) static int request_sga_clock(u8 clock, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) val = readl(PRCM_CGATING_BYPASS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) ret = request_clock(clock, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (!ret && !enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) val = readl(PRCM_CGATING_BYPASS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) writel(val & ~PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) static inline bool plldsi_locked(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) return (readl(PRCM_PLLDSI_LOCKP) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3)) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) static int request_plldsi(bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) int r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI), (enable ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) PRCM_MMIP_LS_CLAMP_CLR : PRCM_MMIP_LS_CLAMP_SET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) val = readl(PRCM_PLLDSI_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) val |= PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) writel(val, PRCM_PLLDSI_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) bool locked = plldsi_locked();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) for (i = 10; !locked && (i > 0); --i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) locked = plldsi_locked();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) if (locked) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) writel(PRCM_APE_RESETN_DSIPLL_RESETN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) PRCM_APE_RESETN_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) PRCM_MMIP_LS_CLAMP_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) writel(val, PRCM_PLLDSI_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) r = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) writel(PRCM_APE_RESETN_DSIPLL_RESETN, PRCM_APE_RESETN_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) static int request_dsiclk(u8 n, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) val = readl(PRCM_DSI_PLLOUT_SEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) val &= ~dsiclk[n].divsel_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) val |= ((enable ? dsiclk[n].divsel : PRCM_DSI_PLLOUT_SEL_OFF) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) dsiclk[n].divsel_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) writel(val, PRCM_DSI_PLLOUT_SEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) static int request_dsiescclk(u8 n, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) val = readl(PRCM_DSITVCLK_DIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) enable ? (val |= dsiescclk[n].en) : (val &= ~dsiescclk[n].en);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) writel(val, PRCM_DSITVCLK_DIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) * @clock: The clock for which the request is made.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) * @enable: Whether the clock should be enabled (true) or disabled (false).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) * This function should only be used by the clock implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) * Do not use it from any other place!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) int db8500_prcmu_request_clock(u8 clock, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) if (clock == PRCMU_SGACLK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) return request_sga_clock(clock, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) else if (clock < PRCMU_NUM_REG_CLOCKS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) return request_clock(clock, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) else if (clock == PRCMU_TIMCLK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) return request_timclk(enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) return request_dsiclk((clock - PRCMU_DSI0CLK), enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) return request_dsiescclk((clock - PRCMU_DSI0ESCCLK), enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) else if (clock == PRCMU_PLLDSI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) return request_plldsi(enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) else if (clock == PRCMU_SYSCLK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) return request_sysclk(enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) else if ((clock == PRCMU_PLLSOC0) || (clock == PRCMU_PLLSOC1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) return request_pll(clock, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) int branch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) u64 rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) u32 d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) u32 div = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) val = readl(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) rate = src_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) rate *= ((val & PRCM_PLL_FREQ_D_MASK) >> PRCM_PLL_FREQ_D_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) d = ((val & PRCM_PLL_FREQ_N_MASK) >> PRCM_PLL_FREQ_N_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) if (d > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) div *= d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) d = ((val & PRCM_PLL_FREQ_R_MASK) >> PRCM_PLL_FREQ_R_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) if (d > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) div *= d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) if (val & PRCM_PLL_FREQ_SELDIV2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) div *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) if ((branch == PLL_FIX) || ((branch == PLL_DIV) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) (val & PRCM_PLL_FREQ_DIV2EN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) ((reg == PRCM_PLLSOC0_FREQ) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) (reg == PRCM_PLLARM_FREQ) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) (reg == PRCM_PLLDDR_FREQ))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) div *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) (void)do_div(rate, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) return (unsigned long)rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) #define ROOT_CLOCK_RATE 38400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) static unsigned long clock_rate(u8 clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) u32 pllsw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) unsigned long rate = ROOT_CLOCK_RATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) val = readl(prcmu_base + clk_mgt[clock].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) if (val & PRCM_CLK_MGT_CLK38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) if (clk_mgt[clock].clk38div && (val & PRCM_CLK_MGT_CLK38DIV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) rate /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) return rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) val |= clk_mgt[clock].pllsw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) rate = pll_rate(PRCM_PLLSOC0_FREQ, rate, clk_mgt[clock].branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) rate = pll_rate(PRCM_PLLSOC1_FREQ, rate, clk_mgt[clock].branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_DDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) rate = pll_rate(PRCM_PLLDDR_FREQ, rate, clk_mgt[clock].branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) if ((clock == PRCMU_SGACLK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) (val & PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) u64 r = (rate * 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) (void)do_div(r, 25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) return (unsigned long)r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) val &= PRCM_CLK_MGT_CLKPLLDIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) return rate / val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) static unsigned long armss_rate(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) u32 r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) unsigned long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) r = readl(PRCM_ARM_CHGCLKREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) /* External ARMCLKFIX clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) rate = pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_FIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) /* Check PRCM_ARM_CHGCLKREQ divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) if (!(r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_DIVSEL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) rate /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) /* Check PRCM_ARMCLKFIX_MGT divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) r = readl(PRCM_ARMCLKFIX_MGT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) r &= PRCM_CLK_MGT_CLKPLLDIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) rate /= r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) } else {/* ARM PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) rate = pll_rate(PRCM_PLLARM_FREQ, ROOT_CLOCK_RATE, PLL_DIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) return rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) static unsigned long dsiclk_rate(u8 n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) u32 divsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) u32 div = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) divsel = readl(PRCM_DSI_PLLOUT_SEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) divsel = ((divsel & dsiclk[n].divsel_mask) >> dsiclk[n].divsel_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) if (divsel == PRCM_DSI_PLLOUT_SEL_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) divsel = dsiclk[n].divsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) dsiclk[n].divsel = divsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) switch (divsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) case PRCM_DSI_PLLOUT_SEL_PHI_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) div *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) case PRCM_DSI_PLLOUT_SEL_PHI_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) div *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) case PRCM_DSI_PLLOUT_SEL_PHI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) PLL_RAW) / div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) static unsigned long dsiescclk_rate(u8 n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) u32 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) div = readl(PRCM_DSITVCLK_DIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) div = ((div & dsiescclk[n].div_mask) >> (dsiescclk[n].div_shift));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) return clock_rate(PRCMU_TVCLK) / max((u32)1, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) unsigned long prcmu_clock_rate(u8 clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) if (clock < PRCMU_NUM_REG_CLOCKS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) return clock_rate(clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) else if (clock == PRCMU_TIMCLK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) return prcmu_is_ulppll_disabled() ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) 32768 : ROOT_CLOCK_RATE / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) else if (clock == PRCMU_SYSCLK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) return ROOT_CLOCK_RATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) else if (clock == PRCMU_PLLSOC0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) else if (clock == PRCMU_PLLSOC1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) else if (clock == PRCMU_ARMSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) return armss_rate();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) else if (clock == PRCMU_PLLDDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) else if (clock == PRCMU_PLLDSI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) PLL_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) return dsiclk_rate(clock - PRCMU_DSI0CLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) return dsiescclk_rate(clock - PRCMU_DSI0ESCCLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) static unsigned long clock_source_rate(u32 clk_mgt_val, int branch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) if (clk_mgt_val & PRCM_CLK_MGT_CLK38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) return ROOT_CLOCK_RATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) clk_mgt_val &= PRCM_CLK_MGT_CLKPLLSW_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_DDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) static u32 clock_divider(unsigned long src_rate, unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) u32 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) div = (src_rate / rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) if (div == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) if (rate < (src_rate / div))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) div++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) return div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) static long round_clock_rate(u8 clock, unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) u32 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) unsigned long src_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) long rounded_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) val = readl(prcmu_base + clk_mgt[clock].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) src_rate = clock_source_rate((val | clk_mgt[clock].pllsw),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) clk_mgt[clock].branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) div = clock_divider(src_rate, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (val & PRCM_CLK_MGT_CLK38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) if (clk_mgt[clock].clk38div) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) if (div > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) div = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) div = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) } else if ((clock == PRCMU_SGACLK) && (div == 3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) u64 r = (src_rate * 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) (void)do_div(r, 25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) if (r <= rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) return (unsigned long)r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) rounded_rate = (src_rate / min(div, (u32)31));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) return rounded_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) static const unsigned long db8500_armss_freqs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) 199680000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) 399360000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) 798720000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) 998400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) /* The DB8520 has slightly higher ARMSS max frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) static const unsigned long db8520_armss_freqs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 199680000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) 399360000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) 798720000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 1152000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) static long round_armss_rate(unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) unsigned long freq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) const unsigned long *freqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) int nfreqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) if (fw_info.version.project == PRCMU_FW_PROJECT_U8520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) freqs = db8520_armss_freqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) nfreqs = ARRAY_SIZE(db8520_armss_freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) freqs = db8500_armss_freqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) nfreqs = ARRAY_SIZE(db8500_armss_freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) /* Find the corresponding arm opp from the cpufreq table. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) for (i = 0; i < nfreqs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) freq = freqs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) if (rate <= freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) /* Return the last valid value, even if a match was not found. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) return freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) #define MIN_PLL_VCO_RATE 600000000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) #define MAX_PLL_VCO_RATE 1680640000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) static long round_plldsi_rate(unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) long rounded_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) unsigned long src_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) unsigned long rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) u32 r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) src_rate = clock_rate(PRCMU_HDMICLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) rem = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) for (r = 7; (rem > 0) && (r > 0); r--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) u64 d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) d = (r * rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) (void)do_div(d, src_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) if (d < 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) d = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) else if (d > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) d = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) d *= src_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) if (((2 * d) < (r * MIN_PLL_VCO_RATE)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) ((r * MAX_PLL_VCO_RATE) < (2 * d)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) (void)do_div(d, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) if (rate < d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) if (rounded_rate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) rounded_rate = (long)d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) if ((rate - d) < rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) rem = (rate - d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) rounded_rate = (long)d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) return rounded_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) static long round_dsiclk_rate(unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) u32 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) unsigned long src_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) long rounded_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) src_rate = pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) PLL_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) div = clock_divider(src_rate, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) rounded_rate = (src_rate / ((div > 2) ? 4 : div));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) return rounded_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) static long round_dsiescclk_rate(unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) u32 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) unsigned long src_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) long rounded_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) src_rate = clock_rate(PRCMU_TVCLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) div = clock_divider(src_rate, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) rounded_rate = (src_rate / min(div, (u32)255));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) return rounded_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) long prcmu_round_clock_rate(u8 clock, unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) if (clock < PRCMU_NUM_REG_CLOCKS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) return round_clock_rate(clock, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) else if (clock == PRCMU_ARMSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) return round_armss_rate(rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) else if (clock == PRCMU_PLLDSI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) return round_plldsi_rate(rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) return round_dsiclk_rate(rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) return round_dsiescclk_rate(rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) return (long)prcmu_clock_rate(clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) static void set_clock_rate(u8 clock, unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) u32 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) unsigned long src_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) spin_lock_irqsave(&clk_mgt_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) /* Grab the HW semaphore. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) val = readl(prcmu_base + clk_mgt[clock].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) src_rate = clock_source_rate((val | clk_mgt[clock].pllsw),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) clk_mgt[clock].branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) div = clock_divider(src_rate, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) if (val & PRCM_CLK_MGT_CLK38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) if (clk_mgt[clock].clk38div) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) if (div > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) val |= PRCM_CLK_MGT_CLK38DIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) val &= ~PRCM_CLK_MGT_CLK38DIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) } else if (clock == PRCMU_SGACLK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) if (div == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) u64 r = (src_rate * 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) (void)do_div(r, 25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) if (r <= rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) val |= PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) div = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) val |= min(div, (u32)31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) val &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) val |= min(div, (u32)31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) writel(val, prcmu_base + clk_mgt[clock].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) /* Release the HW semaphore. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) writel(0, PRCM_SEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) spin_unlock_irqrestore(&clk_mgt_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) static int set_armss_rate(unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) unsigned long freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) u8 opps[] = { ARM_EXTCLK, ARM_50_OPP, ARM_100_OPP, ARM_MAX_OPP };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) const unsigned long *freqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) int nfreqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) if (fw_info.version.project == PRCMU_FW_PROJECT_U8520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) freqs = db8520_armss_freqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) nfreqs = ARRAY_SIZE(db8520_armss_freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) freqs = db8500_armss_freqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) nfreqs = ARRAY_SIZE(db8500_armss_freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) /* Find the corresponding arm opp from the cpufreq table. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) for (i = 0; i < nfreqs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) freq = freqs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) if (rate == freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) if (rate != freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) /* Set the new arm opp. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) pr_debug("SET ARM OPP 0x%02x\n", opps[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) return db8500_prcmu_set_arm_opp(opps[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) static int set_plldsi_rate(unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) unsigned long src_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) unsigned long rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) u32 pll_freq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) u32 r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) src_rate = clock_rate(PRCMU_HDMICLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) rem = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) for (r = 7; (rem > 0) && (r > 0); r--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) u64 d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) u64 hwrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) d = (r * rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) (void)do_div(d, src_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) if (d < 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) d = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) else if (d > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) d = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) hwrate = (d * src_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) if (((2 * hwrate) < (r * MIN_PLL_VCO_RATE)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) ((r * MAX_PLL_VCO_RATE) < (2 * hwrate)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) (void)do_div(hwrate, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) if (rate < hwrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) if (pll_freq == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) (r << PRCM_PLL_FREQ_R_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) if ((rate - hwrate) < rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) rem = (rate - hwrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) (r << PRCM_PLL_FREQ_R_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) if (pll_freq == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) pll_freq |= (1 << PRCM_PLL_FREQ_N_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) writel(pll_freq, PRCM_PLLDSI_FREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) static void set_dsiclk_rate(u8 n, unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) u32 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) div = clock_divider(pll_rate(PRCM_PLLDSI_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) clock_rate(PRCMU_HDMICLK), PLL_RAW), rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) dsiclk[n].divsel = (div == 1) ? PRCM_DSI_PLLOUT_SEL_PHI :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) (div == 2) ? PRCM_DSI_PLLOUT_SEL_PHI_2 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) /* else */ PRCM_DSI_PLLOUT_SEL_PHI_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) val = readl(PRCM_DSI_PLLOUT_SEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) val &= ~dsiclk[n].divsel_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) val |= (dsiclk[n].divsel << dsiclk[n].divsel_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) writel(val, PRCM_DSI_PLLOUT_SEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) static void set_dsiescclk_rate(u8 n, unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) u32 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) div = clock_divider(clock_rate(PRCMU_TVCLK), rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) val = readl(PRCM_DSITVCLK_DIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) val &= ~dsiescclk[n].div_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) val |= (min(div, (u32)255) << dsiescclk[n].div_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) writel(val, PRCM_DSITVCLK_DIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) int prcmu_set_clock_rate(u8 clock, unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) if (clock < PRCMU_NUM_REG_CLOCKS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) set_clock_rate(clock, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) else if (clock == PRCMU_ARMSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) return set_armss_rate(rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) else if (clock == PRCMU_PLLDSI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) return set_plldsi_rate(rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) set_dsiclk_rate((clock - PRCMU_DSI0CLK), rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) set_dsiescclk_rate((clock - PRCMU_DSI0ESCCLK), rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) int db8500_prcmu_config_esram0_deep_sleep(u8 state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) (state < ESRAM0_DEEP_SLEEP_STATE_OFF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) mutex_lock(&mb4_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) writeb(MB4H_MEM_ST, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) writeb(((DDR_PWR_STATE_OFFHIGHLAT << 4) | DDR_PWR_STATE_ON),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) writeb(DDR_PWR_STATE_ON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) writeb(state, (tcdm_base + PRCM_REQ_MB4_ESRAM0_ST));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) wait_for_completion(&mb4_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) mutex_unlock(&mb4_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) int db8500_prcmu_config_hotdog(u8 threshold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) mutex_lock(&mb4_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) writeb(threshold, (tcdm_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) writeb(MB4H_HOTDOG, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) wait_for_completion(&mb4_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) mutex_unlock(&mb4_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) int db8500_prcmu_config_hotmon(u8 low, u8 high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) mutex_lock(&mb4_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) writeb(low, (tcdm_base + PRCM_REQ_MB4_HOTMON_LOW));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) writeb(high, (tcdm_base + PRCM_REQ_MB4_HOTMON_HIGH));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) writeb((HOTMON_CONFIG_LOW | HOTMON_CONFIG_HIGH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) (tcdm_base + PRCM_REQ_MB4_HOTMON_CONFIG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) writeb(MB4H_HOTMON, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) wait_for_completion(&mb4_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) mutex_unlock(&mb4_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) EXPORT_SYMBOL_GPL(db8500_prcmu_config_hotmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) static int config_hot_period(u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) mutex_lock(&mb4_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) writew(val, (tcdm_base + PRCM_REQ_MB4_HOT_PERIOD));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) writeb(MB4H_HOT_PERIOD, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) wait_for_completion(&mb4_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) mutex_unlock(&mb4_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) int db8500_prcmu_start_temp_sense(u16 cycles32k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) if (cycles32k == 0xFFFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) return config_hot_period(cycles32k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) EXPORT_SYMBOL_GPL(db8500_prcmu_start_temp_sense);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) int db8500_prcmu_stop_temp_sense(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) return config_hot_period(0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) EXPORT_SYMBOL_GPL(db8500_prcmu_stop_temp_sense);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) mutex_lock(&mb4_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) writeb(d0, (tcdm_base + PRCM_REQ_MB4_A9WDOG_0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) writeb(d1, (tcdm_base + PRCM_REQ_MB4_A9WDOG_1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) writeb(d2, (tcdm_base + PRCM_REQ_MB4_A9WDOG_2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) writeb(d3, (tcdm_base + PRCM_REQ_MB4_A9WDOG_3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) writeb(cmd, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) wait_for_completion(&mb4_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) mutex_unlock(&mb4_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) BUG_ON(num == 0 || num > 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) sleep_auto_off ? A9WDOG_AUTO_OFF_EN :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) A9WDOG_AUTO_OFF_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) EXPORT_SYMBOL(db8500_prcmu_config_a9wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) int db8500_prcmu_enable_a9wdog(u8 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) EXPORT_SYMBOL(db8500_prcmu_enable_a9wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) int db8500_prcmu_disable_a9wdog(u8 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) EXPORT_SYMBOL(db8500_prcmu_disable_a9wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) int db8500_prcmu_kick_a9wdog(u8 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) EXPORT_SYMBOL(db8500_prcmu_kick_a9wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) * timeout is 28 bit, in ms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) int db8500_prcmu_load_a9wdog(u8 id, u32 timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) return prcmu_a9wdog(MB4H_A9WDOG_LOAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) (id & A9WDOG_ID_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) * Put the lowest 28 bits of timeout at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) * offset 4. Four first bits are used for id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) (u8)((timeout << 4) & 0xf0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) (u8)((timeout >> 4) & 0xff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) (u8)((timeout >> 12) & 0xff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) (u8)((timeout >> 20) & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) EXPORT_SYMBOL(db8500_prcmu_load_a9wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) * prcmu_abb_read() - Read register value(s) from the ABB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) * @slave: The I2C slave address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) * @reg: The (start) register address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) * @value: The read out value(s).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) * @size: The number of registers to read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) * Reads register value(s) from the ABB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) * @size has to be 1 for the current firmware version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) if (size != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) mutex_lock(&mb5_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) writeb(0, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) writeb(0, (tcdm_base + PRCM_REQ_MB5_I2C_VAL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) if (!wait_for_completion_timeout(&mb5_transfer.work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) msecs_to_jiffies(20000))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) r = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) if (!r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) *value = mb5_transfer.ack.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) mutex_unlock(&mb5_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) * prcmu_abb_write_masked() - Write masked register value(s) to the ABB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) * @slave: The I2C slave address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) * @reg: The (start) register address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) * @value: The value(s) to write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) * @mask: The mask(s) to use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) * @size: The number of registers to write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) * Writes masked register value(s) to the ABB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) * For each @value, only the bits set to 1 in the corresponding @mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) * will be written. The other bits are not changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) * @size has to be 1 for the current firmware version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) if (size != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) mutex_lock(&mb5_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) writeb(~*mask, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) writeb(*value, (tcdm_base + PRCM_REQ_MB5_I2C_VAL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) if (!wait_for_completion_timeout(&mb5_transfer.work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) msecs_to_jiffies(20000))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) r = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) mutex_unlock(&mb5_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) * prcmu_abb_write() - Write register value(s) to the ABB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) * @slave: The I2C slave address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) * @reg: The (start) register address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) * @value: The value(s) to write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) * @size: The number of registers to write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) * Writes register value(s) to the ABB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) * @size has to be 1 for the current firmware version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) u8 mask = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) return prcmu_abb_write_masked(slave, reg, value, &mask, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) int prcmu_ac_wake_req(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) mutex_lock(&mb0_transfer.ac_wake_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) val = readl(PRCM_HOSTACCESS_REQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) atomic_set(&ac_wake_req_state, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) * Force Modem Wake-up before hostaccess_req ping-pong.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) * It prevents Modem to enter in Sleep while acking the hostaccess
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) * request. The 31us delay has been calculated by HWI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) val |= PRCM_HOSTACCESS_REQ_WAKE_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) writel(val, PRCM_HOSTACCESS_REQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) udelay(31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) val |= PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) writel(val, PRCM_HOSTACCESS_REQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) msecs_to_jiffies(5000))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) unlock_and_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) mutex_unlock(&mb0_transfer.ac_wake_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) * prcmu_ac_sleep_req - called when ARM no longer needs to talk to modem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) void prcmu_ac_sleep_req(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) mutex_lock(&mb0_transfer.ac_wake_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) val = readl(PRCM_HOSTACCESS_REQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) PRCM_HOSTACCESS_REQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) msecs_to_jiffies(5000))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) atomic_set(&ac_wake_req_state, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) unlock_and_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) mutex_unlock(&mb0_transfer.ac_wake_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) bool db8500_prcmu_is_ac_wake_requested(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) return (atomic_read(&ac_wake_req_state) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) * db8500_prcmu_system_reset - System reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) * Saves the reset reason code and then sets the APE_SOFTRST register which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) * fires interrupt to fw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) * @reset_code: The reason for system reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) void db8500_prcmu_system_reset(u16 reset_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) writel(1, PRCM_APE_SOFTRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) * db8500_prcmu_get_reset_code - Retrieve SW reset reason code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) * Retrieves the reset reason code stored by prcmu_system_reset() before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) * last restart.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) u16 db8500_prcmu_get_reset_code(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) return readw(tcdm_base + PRCM_SW_RST_REASON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) * db8500_prcmu_reset_modem - ask the PRCMU to reset modem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) void db8500_prcmu_modem_reset(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) mutex_lock(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) writeb(MB1H_RESET_MODEM, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) wait_for_completion(&mb1_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) * No need to check return from PRCMU as modem should go in reset state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) * This state is already managed by upper layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) mutex_unlock(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) static void ack_dbb_wakeup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) spin_lock_irqsave(&mb0_transfer.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) writeb(MB0H_READ_WAKEUP_ACK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) spin_unlock_irqrestore(&mb0_transfer.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) static inline void print_unknown_header_warning(u8 n, u8 header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) pr_warn("prcmu: Unknown message header (%d) in mailbox %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) header, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) static bool read_mailbox_0(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) bool r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) u32 ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) unsigned int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) u8 header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) header = readb(tcdm_base + PRCM_MBOX_HEADER_ACK_MB0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) switch (header) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) case MB0H_WAKEUP_EXE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) case MB0H_WAKEUP_SLEEP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) ev = readl(tcdm_base + PRCM_ACK_MB0_WAKEUP_1_8500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) ev = readl(tcdm_base + PRCM_ACK_MB0_WAKEUP_0_8500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) if (ev & (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) complete(&mb0_transfer.ac_wake_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) if (ev & WAKEUP_BIT_SYSCLK_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) complete(&mb3_transfer.sysclk_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) ev &= mb0_transfer.req.dbb_irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) if (ev & prcmu_irq_bit[n])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) generic_handle_irq(irq_find_mapping(db8500_irq_domain, n));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) r = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) print_unknown_header_warning(0, header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) r = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) writel(MBOX_BIT(0), PRCM_ARM_IT1_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) static bool read_mailbox_1(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) mb1_transfer.ack.header = readb(tcdm_base + PRCM_MBOX_HEADER_REQ_MB1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) mb1_transfer.ack.arm_opp = readb(tcdm_base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) PRCM_ACK_MB1_CURRENT_ARM_OPP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) mb1_transfer.ack.ape_opp = readb(tcdm_base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) PRCM_ACK_MB1_CURRENT_APE_OPP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) mb1_transfer.ack.ape_voltage_status = readb(tcdm_base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) PRCM_ACK_MB1_APE_VOLTAGE_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) complete(&mb1_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) static bool read_mailbox_2(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) mb2_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB2_DPS_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) complete(&mb2_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) static bool read_mailbox_3(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) static bool read_mailbox_4(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) u8 header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) bool do_complete = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) header = readb(tcdm_base + PRCM_MBOX_HEADER_REQ_MB4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) switch (header) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) case MB4H_MEM_ST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) case MB4H_HOTDOG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) case MB4H_HOTMON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) case MB4H_HOT_PERIOD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) case MB4H_A9WDOG_CONF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) case MB4H_A9WDOG_EN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) case MB4H_A9WDOG_DIS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) case MB4H_A9WDOG_LOAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) case MB4H_A9WDOG_KICK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) print_unknown_header_warning(4, header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) do_complete = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) if (do_complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) complete(&mb4_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) static bool read_mailbox_5(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) mb5_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB5_I2C_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) mb5_transfer.ack.value = readb(tcdm_base + PRCM_ACK_MB5_I2C_VAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) complete(&mb5_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) static bool read_mailbox_6(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) writel(MBOX_BIT(6), PRCM_ARM_IT1_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) static bool read_mailbox_7(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) static bool (* const read_mailbox[NUM_MB])(void) = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) read_mailbox_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) read_mailbox_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) read_mailbox_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) read_mailbox_3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) read_mailbox_4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) read_mailbox_5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) read_mailbox_6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) read_mailbox_7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) static irqreturn_t prcmu_irq_handler(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) u32 bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) u8 n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) irqreturn_t r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) bits = (readl(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) if (unlikely(!bits))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) r = IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) for (n = 0; bits; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) if (bits & MBOX_BIT(n)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) bits -= MBOX_BIT(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) if (read_mailbox[n]())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) r = IRQ_WAKE_THREAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) static irqreturn_t prcmu_irq_thread_fn(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) ack_dbb_wakeup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) static void prcmu_mask_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) spin_lock_irqsave(&mb0_transfer.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) config_wakeups();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) spin_unlock_irqrestore(&mb0_transfer.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) static void prcmu_irq_mask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->hwirq];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) if (d->irq != IRQ_PRCMU_CA_SLEEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) schedule_work(&mb0_transfer.mask_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) static void prcmu_irq_unmask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->hwirq];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) if (d->irq != IRQ_PRCMU_CA_SLEEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) schedule_work(&mb0_transfer.mask_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) static void noop(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) static struct irq_chip prcmu_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) .name = "prcmu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) .irq_disable = prcmu_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) .irq_ack = noop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) .irq_mask = prcmu_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) .irq_unmask = prcmu_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) static char *fw_project_name(u32 project)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) switch (project) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) case PRCMU_FW_PROJECT_U8500:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) return "U8500";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) case PRCMU_FW_PROJECT_U8400:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) return "U8400";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) case PRCMU_FW_PROJECT_U9500:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) return "U9500";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) case PRCMU_FW_PROJECT_U8500_MBB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) return "U8500 MBB";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) case PRCMU_FW_PROJECT_U8500_C1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) return "U8500 C1";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) case PRCMU_FW_PROJECT_U8500_C2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) return "U8500 C2";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) case PRCMU_FW_PROJECT_U8500_C3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) return "U8500 C3";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) case PRCMU_FW_PROJECT_U8500_C4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) return "U8500 C4";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) case PRCMU_FW_PROJECT_U9500_MBL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) return "U9500 MBL";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) case PRCMU_FW_PROJECT_U8500_MBL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) return "U8500 MBL";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) case PRCMU_FW_PROJECT_U8500_MBL2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) return "U8500 MBL2";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) case PRCMU_FW_PROJECT_U8520:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) return "U8520 MBL";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) case PRCMU_FW_PROJECT_U8420:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) return "U8420";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) case PRCMU_FW_PROJECT_U8420_SYSCLK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) return "U8420-sysclk";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) case PRCMU_FW_PROJECT_U9540:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) return "U9540";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) case PRCMU_FW_PROJECT_A9420:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) return "A9420";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) case PRCMU_FW_PROJECT_L8540:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) return "L8540";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) case PRCMU_FW_PROJECT_L8580:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) return "L8580";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) return "Unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) static int db8500_irq_map(struct irq_domain *d, unsigned int virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) irq_hw_number_t hwirq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) irq_set_chip_and_handler(virq, &prcmu_irq_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) handle_simple_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) static const struct irq_domain_ops db8500_irq_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) .map = db8500_irq_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) .xlate = irq_domain_xlate_twocell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) static int db8500_irq_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) db8500_irq_domain = irq_domain_add_simple(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) np, NUM_PRCMU_WAKEUPS, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) &db8500_irq_ops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) if (!db8500_irq_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) pr_err("Failed to create irqdomain\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) /* All wakeups will be used, so create mappings for all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) for (i = 0; i < NUM_PRCMU_WAKEUPS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) irq_create_mapping(db8500_irq_domain, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) static void dbx500_fw_version_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) void __iomem *tcpm_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) u32 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) tcpm_base = of_iomap(np, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) if (!tcpm_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) pr_err("no prcmu tcpm mem region provided\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) version = readl(tcpm_base + DB8500_PRCMU_FW_VERSION_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) fw_info.version.project = (version & 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) fw_info.version.api_version = (version >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) fw_info.version.func_version = (version >> 16) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) fw_info.version.errata = (version >> 24) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) strncpy(fw_info.version.project_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) fw_project_name(fw_info.version.project),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) PRCMU_FW_PROJECT_NAME_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) fw_info.valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) pr_info("PRCMU firmware: %s(%d), version %d.%d.%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) fw_info.version.project_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) fw_info.version.project,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) fw_info.version.api_version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) fw_info.version.func_version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) fw_info.version.errata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) iounmap(tcpm_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) void __init db8500_prcmu_early_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) * This is a temporary remap to bring up the clocks. It is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) * subsequently replaces with a real remap. After the merge of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) * the mailbox subsystem all of this early code goes away, and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) * clock driver can probe independently. An early initcall will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) * still be needed, but it can be diverted into drivers/clk/ux500.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) prcmu_base = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) if (!prcmu_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) pr_err("%s: ioremap() of prcmu registers failed!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) dbx500_fw_version_init(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) spin_lock_init(&mb0_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) spin_lock_init(&mb0_transfer.dbb_irqs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) mutex_init(&mb0_transfer.ac_wake_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) init_completion(&mb0_transfer.ac_wake_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) mutex_init(&mb1_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) init_completion(&mb1_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) mb1_transfer.ape_opp = APE_NO_CHANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) mutex_init(&mb2_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) init_completion(&mb2_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) spin_lock_init(&mb2_transfer.auto_pm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) spin_lock_init(&mb3_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) mutex_init(&mb3_transfer.sysclk_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) init_completion(&mb3_transfer.sysclk_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) mutex_init(&mb4_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) init_completion(&mb4_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) mutex_init(&mb5_transfer.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) init_completion(&mb5_transfer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) static void init_prcm_registers(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) val = readl(PRCM_A9PL_FORCE_CLKEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) val &= ~(PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) writel(val, (PRCM_A9PL_FORCE_CLKEN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) * Power domain switches (ePODs) modeled as regulators for the DB8500 SoC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) static struct regulator_consumer_supply db8500_vape_consumers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) REGULATOR_SUPPLY("v-ape", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) REGULATOR_SUPPLY("v-i2c", "nmk-i2c.0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) REGULATOR_SUPPLY("v-i2c", "nmk-i2c.1"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) REGULATOR_SUPPLY("v-i2c", "nmk-i2c.2"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) REGULATOR_SUPPLY("v-i2c", "nmk-i2c.3"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) REGULATOR_SUPPLY("v-i2c", "nmk-i2c.4"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) /* "v-mmc" changed to "vcore" in the mainline kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) REGULATOR_SUPPLY("vcore", "sdi0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) REGULATOR_SUPPLY("vcore", "sdi1"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) REGULATOR_SUPPLY("vcore", "sdi2"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) REGULATOR_SUPPLY("vcore", "sdi3"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) REGULATOR_SUPPLY("vcore", "sdi4"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) REGULATOR_SUPPLY("v-dma", "dma40.0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) REGULATOR_SUPPLY("v-ape", "ab8500-usb.0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) /* "v-uart" changed to "vcore" in the mainline kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) REGULATOR_SUPPLY("vcore", "uart0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) REGULATOR_SUPPLY("vcore", "uart1"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) REGULATOR_SUPPLY("vcore", "uart2"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) REGULATOR_SUPPLY("v-hsi", "ste_hsi.0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) static struct regulator_consumer_supply db8500_vsmps2_consumers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) /* AV8100 regulator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) REGULATOR_SUPPLY("hdmi_1v8", "0-0070"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) REGULATOR_SUPPLY("vsupply", "b2r2_bus"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) REGULATOR_SUPPLY("vsupply", "mcde"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) /* SVA MMDSP regulator switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) static struct regulator_consumer_supply db8500_svammdsp_consumers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) REGULATOR_SUPPLY("sva-mmdsp", "cm_control"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) /* SVA pipe regulator switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) static struct regulator_consumer_supply db8500_svapipe_consumers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) REGULATOR_SUPPLY("sva-pipe", "cm_control"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) /* SIA MMDSP regulator switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) static struct regulator_consumer_supply db8500_siammdsp_consumers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) REGULATOR_SUPPLY("sia-mmdsp", "cm_control"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) /* SIA pipe regulator switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) static struct regulator_consumer_supply db8500_siapipe_consumers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) REGULATOR_SUPPLY("sia-pipe", "cm_control"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) static struct regulator_consumer_supply db8500_sga_consumers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) REGULATOR_SUPPLY("v-mali", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) /* ESRAM1 and 2 regulator switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) static struct regulator_consumer_supply db8500_esram12_consumers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) REGULATOR_SUPPLY("esram12", "cm_control"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) /* ESRAM3 and 4 regulator switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) static struct regulator_consumer_supply db8500_esram34_consumers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) REGULATOR_SUPPLY("v-esram34", "mcde"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) REGULATOR_SUPPLY("esram34", "cm_control"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) REGULATOR_SUPPLY("lcla_esram", "dma40.0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) [DB8500_REGULATOR_VAPE] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) .name = "db8500-vape",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) .always_on = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) .consumer_supplies = db8500_vape_consumers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) .num_consumer_supplies = ARRAY_SIZE(db8500_vape_consumers),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) [DB8500_REGULATOR_VARM] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) .name = "db8500-varm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) [DB8500_REGULATOR_VMODEM] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) .name = "db8500-vmodem",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) [DB8500_REGULATOR_VPLL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) .name = "db8500-vpll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) [DB8500_REGULATOR_VSMPS1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) .name = "db8500-vsmps1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) [DB8500_REGULATOR_VSMPS2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) .name = "db8500-vsmps2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) .consumer_supplies = db8500_vsmps2_consumers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) .num_consumer_supplies = ARRAY_SIZE(db8500_vsmps2_consumers),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) [DB8500_REGULATOR_VSMPS3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) .name = "db8500-vsmps3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) [DB8500_REGULATOR_VRF1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) .name = "db8500-vrf1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) [DB8500_REGULATOR_SWITCH_SVAMMDSP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) /* dependency to u8500-vape is handled outside regulator framework */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) .name = "db8500-sva-mmdsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) .consumer_supplies = db8500_svammdsp_consumers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) .num_consumer_supplies = ARRAY_SIZE(db8500_svammdsp_consumers),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) /* "ret" means "retention" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) .name = "db8500-sva-mmdsp-ret",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) [DB8500_REGULATOR_SWITCH_SVAPIPE] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) /* dependency to u8500-vape is handled outside regulator framework */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) .name = "db8500-sva-pipe",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) .consumer_supplies = db8500_svapipe_consumers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) [DB8500_REGULATOR_SWITCH_SIAMMDSP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) /* dependency to u8500-vape is handled outside regulator framework */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) .name = "db8500-sia-mmdsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) .consumer_supplies = db8500_siammdsp_consumers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) .num_consumer_supplies = ARRAY_SIZE(db8500_siammdsp_consumers),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) .name = "db8500-sia-mmdsp-ret",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) [DB8500_REGULATOR_SWITCH_SIAPIPE] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) /* dependency to u8500-vape is handled outside regulator framework */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) .name = "db8500-sia-pipe",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) .consumer_supplies = db8500_siapipe_consumers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) .num_consumer_supplies = ARRAY_SIZE(db8500_siapipe_consumers),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) [DB8500_REGULATOR_SWITCH_SGA] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) .supply_regulator = "db8500-vape",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) .name = "db8500-sga",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) .consumer_supplies = db8500_sga_consumers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) .num_consumer_supplies = ARRAY_SIZE(db8500_sga_consumers),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) .supply_regulator = "db8500-vape",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) .name = "db8500-b2r2-mcde",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) .consumer_supplies = db8500_b2r2_mcde_consumers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) [DB8500_REGULATOR_SWITCH_ESRAM12] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) * esram12 is set in retention and supplied by Vsafe when Vape is off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) * no need to hold Vape
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) .name = "db8500-esram12",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) .consumer_supplies = db8500_esram12_consumers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) .num_consumer_supplies = ARRAY_SIZE(db8500_esram12_consumers),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) [DB8500_REGULATOR_SWITCH_ESRAM12RET] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) .name = "db8500-esram12-ret",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) [DB8500_REGULATOR_SWITCH_ESRAM34] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) * esram34 is set in retention and supplied by Vsafe when Vape is off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) * no need to hold Vape
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) .name = "db8500-esram34",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) .consumer_supplies = db8500_esram34_consumers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) .num_consumer_supplies = ARRAY_SIZE(db8500_esram34_consumers),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) [DB8500_REGULATOR_SWITCH_ESRAM34RET] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) .constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) .name = "db8500-esram34-ret",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) .valid_ops_mask = REGULATOR_CHANGE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) static struct ux500_wdt_data db8500_wdt_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) .timeout = 600, /* 10 minutes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) .has_28_bits_resolution = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) static const struct mfd_cell common_prcmu_devs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) .name = "ux500_wdt",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) .platform_data = &db8500_wdt_pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) .pdata_size = sizeof(db8500_wdt_pdata),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) .id = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) static const struct mfd_cell db8500_prcmu_devs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) OF_MFD_CELL("db8500-prcmu-regulators", NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) &db8500_regulators, sizeof(db8500_regulators), 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) "stericsson,db8500-prcmu-regulator"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) OF_MFD_CELL("cpuidle-dbx500",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) NULL, NULL, 0, 0, "stericsson,cpuidle-dbx500"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) OF_MFD_CELL("db8500-thermal",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) NULL, NULL, 0, 0, "stericsson,db8500-thermal"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) static int db8500_prcmu_register_ab8500(struct device *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) struct resource ab850x_resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) const struct mfd_cell ab8500_cell = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) .name = "ab8500-core",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) .of_compatible = "stericsson,ab8500",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) .id = AB8500_VERSION_AB8500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) .resources = &ab850x_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) .num_resources = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) const struct mfd_cell ab8505_cell = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) .name = "ab8505-core",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) .of_compatible = "stericsson,ab8505",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) .id = AB8500_VERSION_AB8505,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) .resources = &ab850x_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) .num_resources = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) const struct mfd_cell *ab850x_cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) if (!parent->of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) /* Look up the device node, sneak the IRQ out of it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) for_each_child_of_node(parent->of_node, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) if (of_device_is_compatible(np, ab8500_cell.of_compatible)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) ab850x_cell = &ab8500_cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) if (of_device_is_compatible(np, ab8505_cell.of_compatible)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) ab850x_cell = &ab8505_cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) dev_info(parent, "could not find AB850X node in the device tree\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) of_irq_to_resource_table(np, &ab850x_resource, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) return mfd_add_devices(parent, 0, ab850x_cell, 1, NULL, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) static int db8500_prcmu_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) int irq = 0, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) dev_err(&pdev->dev, "no prcmu memory region provided\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) prcmu_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) if (!prcmu_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) "failed to ioremap prcmu register memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) init_prcm_registers();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) dev_err(&pdev->dev, "no prcmu tcdm region provided\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) tcdm_base = devm_ioremap(&pdev->dev, res->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) if (!tcdm_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) "failed to ioremap prcmu-tcdm register memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) /* Clean up the mailbox interrupts after pre-kernel code. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) if (irq <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) err = request_threaded_irq(irq, prcmu_irq_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) db8500_irq_init(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) err = mfd_add_devices(&pdev->dev, 0, common_prcmu_devs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) ARRAY_SIZE(common_prcmu_devs), NULL, 0, db8500_irq_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) pr_err("prcmu: Failed to add subdevices\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) /* TODO: Remove restriction when clk definitions are available. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) if (!of_machine_is_compatible("st-ericsson,u8540")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) ARRAY_SIZE(db8500_prcmu_devs), NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) db8500_irq_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) mfd_remove_devices(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) pr_err("prcmu: Failed to add subdevices\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) err = db8500_prcmu_register_ab8500(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) mfd_remove_devices(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) pr_err("prcmu: Failed to add ab8500 subdevice\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) pr_info("DB8500 PRCMU initialized\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) static const struct of_device_id db8500_prcmu_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) { .compatible = "stericsson,db8500-prcmu"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) static struct platform_driver db8500_prcmu_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) .name = "db8500-prcmu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) .of_match_table = db8500_prcmu_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) .probe = db8500_prcmu_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) static int __init db8500_prcmu_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) return platform_driver_register(&db8500_prcmu_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) core_initcall(db8500_prcmu_init);