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