Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * CPU frequency scaling for Broadcom SoCs with AVS firmware that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * supports DVS or DVFS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (c) 2016 Broadcom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * This program is free software; you can redistribute it and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * modify it under the terms of the GNU General Public License as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * published by the Free Software Foundation version 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * kind, whether express or implied; without even the implied warranty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * "AVS" is the name of a firmware developed at Broadcom. It derives
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * its name from the technique called "Adaptive Voltage Scaling".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * Adaptive voltage scaling was the original purpose of this firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * The AVS firmware still supports "AVS mode", where all it does is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * adaptive voltage scaling. However, on some newer Broadcom SoCs, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * AVS Firmware, despite its unchanged name, also supports DFS mode and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * DVFS mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * In the context of this document and the related driver, "AVS" by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * itself always means the Broadcom firmware and never refers to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  * technique called "Adaptive Voltage Scaling".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * The Broadcom STB AVS CPUfreq driver provides voltage and frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * scaling on Broadcom SoCs using AVS firmware with support for DFS and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * DVFS. The AVS firmware is running on its own co-processor. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * driver supports both uniprocessor (UP) and symmetric multiprocessor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  * (SMP) systems which share clock and voltage across all CPUs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  * Actual voltage and frequency scaling is done solely by the AVS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  * firmware. This driver does not change frequency or voltage itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  * It provides a standard CPUfreq interface to the rest of the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  * and to userland. It interfaces with the AVS firmware to effect the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  * requested changes and to report back the current system status in a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * way that is expected by existing tools.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #include <linux/cpufreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #include <linux/semaphore.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) /* Max number of arguments AVS calls take */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) #define AVS_MAX_CMD_ARGS	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * This macro is used to generate AVS parameter register offsets. For
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * x >= AVS_MAX_CMD_ARGS, it returns 0 to protect against accidental memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * access outside of the parameter range. (Offset 0 is the first parameter.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) #define AVS_PARAM_MULT(x)	((x) < AVS_MAX_CMD_ARGS ? (x) : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) /* AVS Mailbox Register offsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) #define AVS_MBOX_COMMAND	0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) #define AVS_MBOX_STATUS		0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) #define AVS_MBOX_VOLTAGE0	0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) #define AVS_MBOX_TEMP0		0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) #define AVS_MBOX_PV0		0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) #define AVS_MBOX_MV0		0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) #define AVS_MBOX_PARAM(x)	(0x18 + AVS_PARAM_MULT(x) * sizeof(u32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) #define AVS_MBOX_REVISION	0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) #define AVS_MBOX_PSTATE		0x2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) #define AVS_MBOX_HEARTBEAT	0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) #define AVS_MBOX_MAGIC		0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) #define AVS_MBOX_SIGMA_HVT	0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) #define AVS_MBOX_SIGMA_SVT	0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) #define AVS_MBOX_VOLTAGE1	0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) #define AVS_MBOX_TEMP1		0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) #define AVS_MBOX_PV1		0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) #define AVS_MBOX_MV1		0x4c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) #define AVS_MBOX_FREQUENCY	0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) /* AVS Commands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) #define AVS_CMD_AVAILABLE	0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) #define AVS_CMD_DISABLE		0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) #define AVS_CMD_ENABLE		0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) #define AVS_CMD_S2_ENTER	0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) #define AVS_CMD_S2_EXIT		0x13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) #define AVS_CMD_BBM_ENTER	0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) #define AVS_CMD_BBM_EXIT	0x15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) #define AVS_CMD_S3_ENTER	0x16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) #define AVS_CMD_S3_EXIT		0x17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) #define AVS_CMD_BALANCE		0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) /* PMAP and P-STATE commands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) #define AVS_CMD_GET_PMAP	0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) #define AVS_CMD_SET_PMAP	0x31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) #define AVS_CMD_GET_PSTATE	0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) #define AVS_CMD_SET_PSTATE	0x41
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) /* Different modes AVS supports (for GET_PMAP/SET_PMAP) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define AVS_MODE_AVS		0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define AVS_MODE_DFS		0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define AVS_MODE_DVS		0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define AVS_MODE_DVFS		0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)  * PMAP parameter p1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)  * unused:31-24, mdiv_p0:23-16, unused:15-14, pdiv:13-10 , ndiv_int:9-0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define NDIV_INT_SHIFT		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define NDIV_INT_MASK		0x3ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define PDIV_SHIFT		10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define PDIV_MASK		0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define MDIV_P0_SHIFT		16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define MDIV_P0_MASK		0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  * PMAP parameter p2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  * mdiv_p4:31-24, mdiv_p3:23-16, mdiv_p2:15:8, mdiv_p1:7:0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define MDIV_P1_SHIFT		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define MDIV_P1_MASK		0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define MDIV_P2_SHIFT		8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define MDIV_P2_MASK		0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define MDIV_P3_SHIFT		16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define MDIV_P3_MASK		0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define MDIV_P4_SHIFT		24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define MDIV_P4_MASK		0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* Different P-STATES AVS supports (for GET_PSTATE/SET_PSTATE) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define AVS_PSTATE_P0		0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define AVS_PSTATE_P1		0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define AVS_PSTATE_P2		0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define AVS_PSTATE_P3		0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define AVS_PSTATE_P4		0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define AVS_PSTATE_MAX		AVS_PSTATE_P4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* CPU L2 Interrupt Controller Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define AVS_CPU_L2_SET0		0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define AVS_CPU_L2_INT_MASK	BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* AVS Command Status Values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define AVS_STATUS_CLEAR	0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* Command/notification accepted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define AVS_STATUS_SUCCESS	0xf0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* Command/notification rejected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define AVS_STATUS_FAILURE	0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* Invalid command/notification (unknown) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define AVS_STATUS_INVALID	0xf1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* Non-AVS modes are not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define AVS_STATUS_NO_SUPP	0xf2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* Cannot set P-State until P-Map supplied */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define AVS_STATUS_NO_MAP	0xf3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* Cannot change P-Map after initial P-Map set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define AVS_STATUS_MAP_SET	0xf4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* Max AVS status; higher numbers are used for debugging */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define AVS_STATUS_MAX		0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* Other AVS related constants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define AVS_LOOP_LIMIT		10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define AVS_TIMEOUT		300 /* in ms; expected completion is < 10ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define AVS_FIRMWARE_MAGIC	0xa11600d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define BRCM_AVS_CPUFREQ_PREFIX	"brcmstb-avs"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define BRCM_AVS_CPUFREQ_NAME	BRCM_AVS_CPUFREQ_PREFIX "-cpufreq"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define BRCM_AVS_CPU_DATA	"brcm,avs-cpu-data-mem"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define BRCM_AVS_CPU_INTR	"brcm,avs-cpu-l2-intr"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define BRCM_AVS_HOST_INTR	"sw_intr"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct pmap {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	unsigned int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	unsigned int p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	unsigned int p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	unsigned int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct private_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	void __iomem *avs_intr_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	struct completion done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	struct semaphore sem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	struct pmap pmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	int host_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static void __iomem *__map_region(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	void __iomem *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	np = of_find_compatible_node(NULL, NULL, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	if (!np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	ptr = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	return ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static unsigned long wait_for_avs_command(struct private_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 					  unsigned long timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	unsigned long time_left = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	/* Event driven, wait for the command interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	if (priv->host_irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		return wait_for_completion_timeout(&priv->done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 						   msecs_to_jiffies(timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	/* Polling for command completion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		time_left = timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		val = readl(priv->base + AVS_MBOX_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	} while (--timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	return time_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static int __issue_avs_command(struct private_data *priv, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 			       unsigned int num_in, unsigned int num_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			       u32 args[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	void __iomem *base = priv->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	unsigned long time_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	ret = down_interruptible(&priv->sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	 * Make sure no other command is currently running: cmd is 0 if AVS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	 * co-processor is idle. Due to the guard above, we should almost never
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	 * have to wait here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	for (i = 0, val = 1; val != 0 && i < AVS_LOOP_LIMIT; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		val = readl(base + AVS_MBOX_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	/* Give the caller a chance to retry if AVS is busy. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	if (i == AVS_LOOP_LIMIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	/* Clear status before we begin. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	writel(AVS_STATUS_CLEAR, base + AVS_MBOX_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	/* Provide input parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	for (i = 0; i < num_in; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		writel(args[i], base + AVS_MBOX_PARAM(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	/* Protect from spurious interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	reinit_completion(&priv->done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	/* Now issue the command & tell firmware to wake up to process it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	writel(cmd, base + AVS_MBOX_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	writel(AVS_CPU_L2_INT_MASK, priv->avs_intr_base + AVS_CPU_L2_SET0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	/* Wait for AVS co-processor to finish processing the command. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	time_left = wait_for_avs_command(priv, AVS_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	 * If the AVS status is not in the expected range, it means AVS didn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	 * complete our command in time, and we return an error. Also, if there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	 * is no "time left", we timed out waiting for the interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	val = readl(base + AVS_MBOX_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	if (time_left == 0 || val == 0 || val > AVS_STATUS_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		dev_err(priv->dev, "AVS command %#x didn't complete in time\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 			cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		dev_err(priv->dev, "    Time left: %u ms, AVS status: %#x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 			jiffies_to_msecs(time_left), val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	/* Process returned values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	for (i = 0; i < num_out; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		args[i] = readl(base + AVS_MBOX_PARAM(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	/* Clear status to tell AVS co-processor we are done. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	writel(AVS_STATUS_CLEAR, base + AVS_MBOX_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	/* Convert firmware errors to errno's as much as possible. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	case AVS_STATUS_INVALID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	case AVS_STATUS_NO_SUPP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		ret = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	case AVS_STATUS_NO_MAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	case AVS_STATUS_MAP_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		ret = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	case AVS_STATUS_FAILURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	up(&priv->sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static irqreturn_t irq_handler(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	struct private_data *priv = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	/* AVS command completed execution. Wake up __issue_avs_command(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	complete(&priv->done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static char *brcm_avs_mode_to_string(unsigned int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	case AVS_MODE_AVS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		return "AVS";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	case AVS_MODE_DFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		return "DFS";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	case AVS_MODE_DVS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		return "DVS";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	case AVS_MODE_DVFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		return "DVFS";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static void brcm_avs_parse_p1(u32 p1, unsigned int *mdiv_p0, unsigned int *pdiv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 			      unsigned int *ndiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	*mdiv_p0 = (p1 >> MDIV_P0_SHIFT) & MDIV_P0_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	*pdiv = (p1 >> PDIV_SHIFT) & PDIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	*ndiv = (p1 >> NDIV_INT_SHIFT) & NDIV_INT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static void brcm_avs_parse_p2(u32 p2, unsigned int *mdiv_p1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 			      unsigned int *mdiv_p2, unsigned int *mdiv_p3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 			      unsigned int *mdiv_p4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	*mdiv_p4 = (p2 >> MDIV_P4_SHIFT) & MDIV_P4_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	*mdiv_p3 = (p2 >> MDIV_P3_SHIFT) & MDIV_P3_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	*mdiv_p2 = (p2 >> MDIV_P2_SHIFT) & MDIV_P2_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	*mdiv_p1 = (p2 >> MDIV_P1_SHIFT) & MDIV_P1_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static int brcm_avs_get_pmap(struct private_data *priv, struct pmap *pmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	u32 args[AVS_MAX_CMD_ARGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	ret = __issue_avs_command(priv, AVS_CMD_GET_PMAP, 0, 4, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	if (ret || !pmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	pmap->mode = args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	pmap->p1 = args[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	pmap->p2 = args[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	pmap->state = args[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static int brcm_avs_set_pmap(struct private_data *priv, struct pmap *pmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	u32 args[AVS_MAX_CMD_ARGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	args[0] = pmap->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	args[1] = pmap->p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	args[2] = pmap->p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	args[3] = pmap->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	return __issue_avs_command(priv, AVS_CMD_SET_PMAP, 4, 0, args);
^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) static int brcm_avs_get_pstate(struct private_data *priv, unsigned int *pstate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	u32 args[AVS_MAX_CMD_ARGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	ret = __issue_avs_command(priv, AVS_CMD_GET_PSTATE, 0, 1, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	*pstate = args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static int brcm_avs_set_pstate(struct private_data *priv, unsigned int pstate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	u32 args[AVS_MAX_CMD_ARGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	args[0] = pstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	return __issue_avs_command(priv, AVS_CMD_SET_PSTATE, 1, 0, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static u32 brcm_avs_get_voltage(void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	return readl(base + AVS_MBOX_VOLTAGE1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static u32 brcm_avs_get_frequency(void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	return readl(base + AVS_MBOX_FREQUENCY) * 1000;	/* in kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)  * We determine which frequencies are supported by cycling through all P-states
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)  * and reading back what frequency we are running at for each P-state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static struct cpufreq_frequency_table *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) brcm_avs_get_freq_table(struct device *dev, struct private_data *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	struct cpufreq_frequency_table *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	unsigned int pstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	/* Remember P-state for later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	ret = brcm_avs_get_pstate(priv, &pstate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	table = devm_kcalloc(dev, AVS_PSTATE_MAX + 1, sizeof(*table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 			     GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	if (!table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	for (i = AVS_PSTATE_P0; i <= AVS_PSTATE_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		ret = brcm_avs_set_pstate(priv, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 			return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 		table[i].frequency = brcm_avs_get_frequency(priv->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		table[i].driver_data = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	table[i].frequency = CPUFREQ_TABLE_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	/* Restore P-state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	ret = brcm_avs_set_pstate(priv, pstate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	return table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^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)  * To ensure the right firmware is running we need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)  *    - check the MAGIC matches what we expect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)  *    - brcm_avs_get_pmap() doesn't return -ENOTSUPP or -EINVAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)  * We need to set up our interrupt handling before calling brcm_avs_get_pmap()!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static bool brcm_avs_is_firmware_loaded(struct private_data *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	u32 magic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	rc = brcm_avs_get_pmap(priv, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	magic = readl(priv->base + AVS_MBOX_MAGIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	return (magic == AVS_FIRMWARE_MAGIC) && ((rc != -ENOTSUPP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		(rc != -EINVAL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static unsigned int brcm_avs_cpufreq_get(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	struct private_data *priv = policy->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	cpufreq_cpu_put(policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	return brcm_avs_get_frequency(priv->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static int brcm_avs_target_index(struct cpufreq_policy *policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 				 unsigned int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	return brcm_avs_set_pstate(policy->driver_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 				  policy->freq_table[index].driver_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static int brcm_avs_suspend(struct cpufreq_policy *policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	struct private_data *priv = policy->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	ret = brcm_avs_get_pmap(priv, &priv->pmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	 * We can't use the P-state returned by brcm_avs_get_pmap(), since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	 * that's the initial P-state from when the P-map was downloaded to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	 * AVS co-processor, not necessarily the P-state we are running at now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	 * So, we get the current P-state explicitly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	ret = brcm_avs_get_pstate(priv, &priv->pmap.state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	/* This is best effort. Nothing to do if it fails. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	(void)__issue_avs_command(priv, AVS_CMD_S2_ENTER, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static int brcm_avs_resume(struct cpufreq_policy *policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	struct private_data *priv = policy->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	/* This is best effort. Nothing to do if it fails. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	(void)__issue_avs_command(priv, AVS_CMD_S2_EXIT, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	ret = brcm_avs_set_pmap(priv, &priv->pmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	if (ret == -EEXIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		struct platform_device *pdev  = cpufreq_get_driver_data();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 		dev_warn(dev, "PMAP was already set\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	return ret;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)  * All initialization code that we only want to execute once goes here. Setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)  * code that can be re-tried on every core (if it failed before) can go into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)  * brcm_avs_cpufreq_init().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) static int brcm_avs_prepare_init(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	struct private_data *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	priv->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	sema_init(&priv->sem, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	init_completion(&priv->done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	platform_set_drvdata(pdev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	priv->base = __map_region(BRCM_AVS_CPU_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	if (!priv->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 		dev_err(dev, "Couldn't find property %s in device tree.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 			BRCM_AVS_CPU_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 		return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	priv->avs_intr_base = __map_region(BRCM_AVS_CPU_INTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	if (!priv->avs_intr_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		dev_err(dev, "Couldn't find property %s in device tree.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 			BRCM_AVS_CPU_INTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 		ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 		goto unmap_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	priv->host_irq = platform_get_irq_byname(pdev, BRCM_AVS_HOST_INTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	ret = devm_request_irq(dev, priv->host_irq, irq_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 			       IRQF_TRIGGER_RISING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 			       BRCM_AVS_HOST_INTR, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	if (ret && priv->host_irq >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 		dev_err(dev, "IRQ request failed: %s (%d) -- %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 			BRCM_AVS_HOST_INTR, priv->host_irq, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		goto unmap_intr_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	if (brcm_avs_is_firmware_loaded(priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	dev_err(dev, "AVS firmware is not loaded or doesn't support DVFS\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) unmap_intr_base:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	iounmap(priv->avs_intr_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) unmap_base:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	iounmap(priv->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) static void brcm_avs_prepare_uninit(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	struct private_data *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	iounmap(priv->avs_intr_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	iounmap(priv->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static int brcm_avs_cpufreq_init(struct cpufreq_policy *policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	struct cpufreq_frequency_table *freq_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	struct private_data *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 	struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	pdev = cpufreq_get_driver_data();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	policy->driver_data = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	freq_table = brcm_avs_get_freq_table(dev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	if (IS_ERR(freq_table)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 		ret = PTR_ERR(freq_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 		dev_err(dev, "Couldn't determine frequency table (%d).\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	policy->freq_table = freq_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	/* All cores share the same clock and thus the same policy. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	cpumask_setall(policy->cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	ret = __issue_avs_command(priv, AVS_CMD_ENABLE, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 		unsigned int pstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 		ret = brcm_avs_get_pstate(priv, &pstate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 		if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 			policy->cur = freq_table[pstate].frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 			dev_info(dev, "registered\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	dev_err(dev, "couldn't initialize driver (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) static ssize_t show_brcm_avs_pstate(struct cpufreq_policy *policy, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	struct private_data *priv = policy->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	unsigned int pstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	if (brcm_avs_get_pstate(priv, &pstate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 		return sprintf(buf, "<unknown>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	return sprintf(buf, "%u\n", pstate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static ssize_t show_brcm_avs_mode(struct cpufreq_policy *policy, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 	struct private_data *priv = policy->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 	struct pmap pmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	if (brcm_avs_get_pmap(priv, &pmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 		return sprintf(buf, "<unknown>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	return sprintf(buf, "%s %u\n", brcm_avs_mode_to_string(pmap.mode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 		pmap.mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) static ssize_t show_brcm_avs_pmap(struct cpufreq_policy *policy, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	unsigned int mdiv_p0, mdiv_p1, mdiv_p2, mdiv_p3, mdiv_p4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 	struct private_data *priv = policy->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	unsigned int ndiv, pdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	struct pmap pmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	if (brcm_avs_get_pmap(priv, &pmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 		return sprintf(buf, "<unknown>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 	brcm_avs_parse_p1(pmap.p1, &mdiv_p0, &pdiv, &ndiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 	brcm_avs_parse_p2(pmap.p2, &mdiv_p1, &mdiv_p2, &mdiv_p3, &mdiv_p4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	return sprintf(buf, "0x%08x 0x%08x %u %u %u %u %u %u %u %u %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 		pmap.p1, pmap.p2, ndiv, pdiv, mdiv_p0, mdiv_p1, mdiv_p2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 		mdiv_p3, mdiv_p4, pmap.mode, pmap.state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) static ssize_t show_brcm_avs_voltage(struct cpufreq_policy *policy, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	struct private_data *priv = policy->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 	return sprintf(buf, "0x%08x\n", brcm_avs_get_voltage(priv->base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static ssize_t show_brcm_avs_frequency(struct cpufreq_policy *policy, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	struct private_data *priv = policy->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 	return sprintf(buf, "0x%08x\n", brcm_avs_get_frequency(priv->base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) cpufreq_freq_attr_ro(brcm_avs_pstate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) cpufreq_freq_attr_ro(brcm_avs_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) cpufreq_freq_attr_ro(brcm_avs_pmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) cpufreq_freq_attr_ro(brcm_avs_voltage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) cpufreq_freq_attr_ro(brcm_avs_frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) static struct freq_attr *brcm_avs_cpufreq_attr[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 	&cpufreq_freq_attr_scaling_available_freqs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	&brcm_avs_pstate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	&brcm_avs_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	&brcm_avs_pmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	&brcm_avs_voltage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	&brcm_avs_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	NULL
^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) static struct cpufreq_driver brcm_avs_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	.flags		= CPUFREQ_NEED_INITIAL_FREQ_CHECK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	.verify		= cpufreq_generic_frequency_table_verify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	.target_index	= brcm_avs_target_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	.get		= brcm_avs_cpufreq_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 	.suspend	= brcm_avs_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	.resume		= brcm_avs_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	.init		= brcm_avs_cpufreq_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	.attr		= brcm_avs_cpufreq_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 	.name		= BRCM_AVS_CPUFREQ_PREFIX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) static int brcm_avs_cpufreq_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	ret = brcm_avs_prepare_init(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	brcm_avs_driver.driver_data = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	ret = cpufreq_register_driver(&brcm_avs_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 		brcm_avs_prepare_uninit(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) static int brcm_avs_cpufreq_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 	ret = cpufreq_unregister_driver(&brcm_avs_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 	WARN_ON(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 	brcm_avs_prepare_uninit(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static const struct of_device_id brcm_avs_cpufreq_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	{ .compatible = BRCM_AVS_CPU_DATA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) MODULE_DEVICE_TABLE(of, brcm_avs_cpufreq_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static struct platform_driver brcm_avs_cpufreq_platdrv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 		.name	= BRCM_AVS_CPUFREQ_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 		.of_match_table = brcm_avs_cpufreq_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 	.probe		= brcm_avs_cpufreq_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 	.remove		= brcm_avs_cpufreq_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) module_platform_driver(brcm_avs_cpufreq_platdrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) MODULE_AUTHOR("Markus Mayer <mmayer@broadcom.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) MODULE_DESCRIPTION("CPUfreq driver for Broadcom STB AVS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) MODULE_LICENSE("GPL");