From patchwork Wed Sep 5 09:59:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Loic Pallardy X-Patchwork-Id: 1408201 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 34C5E40220 for ; Wed, 5 Sep 2012 10:10:47 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1T9CTP-0007zh-8G; Wed, 05 Sep 2012 10:04:42 +0000 Received: from eu1sys200aog116.obsmtp.com ([207.126.144.141]) by merlin.infradead.org with smtps (Exim 4.76 #1 (Red Hat Linux)) id 1T9COm-00057p-4q for linux-arm-kernel@lists.infradead.org; Wed, 05 Sep 2012 10:00:23 +0000 Received: from beta.dmz-ap.st.com ([138.198.100.35]) (using TLSv1) by eu1sys200aob116.postini.com ([207.126.147.11]) with SMTP ID DSNKUEcij4jgWaLYIzzdLktmkZSvrgZubVUl@postini.com; Wed, 05 Sep 2012 09:59:51 UTC Received: from zeta.dmz-ap.st.com (ns6.st.com [138.198.234.13]) by beta.dmz-ap.st.com (STMicroelectronics) with ESMTP id 21649D8; Wed, 5 Sep 2012 09:51:25 +0000 (GMT) Received: from relay2.stm.gmessaging.net (unknown [10.230.100.18]) by zeta.dmz-ap.st.com (STMicroelectronics) with ESMTP id 66FD813C0; Wed, 5 Sep 2012 09:59:39 +0000 (GMT) Received: from exdcvycastm004.EQ1STM.local (alteon-source-exch [10.230.100.61]) (using TLSv1 with cipher RC4-MD5 (128/128 bits)) (Client CN "exdcvycastm004", Issuer "exdcvycastm004" (not verified)) by relay2.stm.gmessaging.net (Postfix) with ESMTPS id 65DBCA8081; Wed, 5 Sep 2012 11:59:34 +0200 (CEST) Received: from lmenx30v.lme.st.com (10.230.100.153) by smtp.stericsson.com (10.230.100.2) with Microsoft SMTP Server (TLS) id 8.3.83.0; Wed, 5 Sep 2012 11:59:38 +0200 From: Loic Pallardy To: Samuel Ortiz , , , Linus Walleij Subject: [PATCH 10/17] mfd: prcmu: dbx500-prmcu creation Date: Wed, 5 Sep 2012 11:59:06 +0200 Message-ID: <1346839153-6465-11-git-send-email-loic.pallardy-ext@stericsson.com> X-Mailer: git-send-email 1.7.11.1 In-Reply-To: <1346839153-6465-1-git-send-email-loic.pallardy-ext@stericsson.com> References: <1346839153-6465-1-git-send-email-loic.pallardy-ext@stericsson.com> MIME-Version: 1.0 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -4.2 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [207.126.144.141 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Loic Pallardy , Loic Pallardy , Michel JAOUEN , STEricsson_nomadik_linux , Loic Pallardy , Lee Jones , LT ST-Ericsson X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Create a generic drivers/mfd/dbx500-prcmu.c Allow supporting and managing several PRCMU IP versions Use dbx500-prcmu new interfaces to abstract prcmu services. Signed-off-by: Michel JAOUEN Signed-off-by: Loic Pallardy Acked-by: Linus Walleij --- drivers/mfd/Kconfig | 10 + drivers/mfd/Makefile | 1 + drivers/mfd/db8500-prcmu.c | 303 ++++++++++++--- drivers/mfd/dbx500-prcmu.c | 813 +++++++++++++++++++++++++++++++++++++++ include/linux/mfd/db8500-prcmu.h | 250 +----------- include/linux/mfd/dbx500-prcmu.h | 547 ++++++++++---------------- 6 files changed, 1288 insertions(+), 636 deletions(-) create mode 100644 drivers/mfd/dbx500-prcmu.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b1a1462..3420844 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -801,10 +801,20 @@ config AB8500_GPADC help AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage +config DBX500_PRCMU + bool "ST-Ericsson DBX500 Power Reset Control Management Unit" + depends on UX500_SOC_DB8500 + help + Select this option to enable support for generic DBX500 Power + Reset and Control Management Unit. you have to select it for + enabling interface with other components like cpufreq, + cpuidle, prcmu-qos-power. + config MFD_DB8500_PRCMU bool "ST-Ericsson DB8500 Power Reset Control Management Unit" depends on UX500_SOC_DB8500 select MFD_CORE + select DBX500_PRCMU help Select this option to enable support for the DB8500 Power Reset and Control Management Unit. This is basically an autonomous diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 79dd22d..42d703a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -106,6 +106,7 @@ obj-$(CONFIG_AB3100_CORE) += ab3100-core.o obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o +obj-$(CONFIG_DBX500_PRCMU) += dbx500-prcmu.o obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o # ab8500-core need to come after db8500-prcmu (which provides the channel) obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index eb327f3..36f7c1d 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -615,12 +615,12 @@ int db8500_prcmu_set_display_clocks(void) return 0; } -u32 db8500_prcmu_read(unsigned int reg) +static u32 db8500_prcmu_read(unsigned int reg) { return readl(_PRCMU_BASE + reg); } -void db8500_prcmu_write(unsigned int reg, u32 value) +static void db8500_prcmu_write(unsigned int reg, u32 value) { unsigned long flags; @@ -629,7 +629,7 @@ void db8500_prcmu_write(unsigned int reg, u32 value) spin_unlock_irqrestore(&prcmu_lock, flags); } -void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value) +static void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value) { u32 val; unsigned long flags; @@ -641,12 +641,12 @@ void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value) spin_unlock_irqrestore(&prcmu_lock, flags); } -struct prcmu_fw_version *prcmu_get_fw_version(void) +static struct prcmu_fw_version *db8500_prcmu_get_fw_version(void) { return fw_info.valid ? &fw_info.version : NULL; } -bool prcmu_has_arm_maxopp(void) +static bool db8500_prcmu_has_arm_maxopp(void) { return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) & PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK; @@ -700,7 +700,7 @@ enum ap_pwrst prcmu_get_xp70_current_state(void) } /** - * prcmu_config_clkout - Configure one of the programmable clock outputs. + * db8500_prcmu_config_clkout - Configure one of the programmable clock outputs. * @clkout: The CLKOUT number (0 or 1). * @source: The clock to be used (one of the PRCMU_CLKSRC_*). * @div: The divider to be applied. @@ -709,7 +709,7 @@ enum ap_pwrst prcmu_get_xp70_current_state(void) * @div should be in the range [1,63] to request a configuration, or 0 to * inform that the configuration is no longer requested. */ -int prcmu_config_clkout(u8 clkout, u8 source, u8 div) +static int db8500_prcmu_config_clkout(u8 clkout, u8 source, u8 div) { static int requests[2]; int r = 0; @@ -794,7 +794,7 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) return 0; } -u8 db8500_prcmu_get_power_state_result(void) +static u8 db8500_prcmu_get_power_state_result(void) { return readb(tcdm_legacy_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS); } @@ -945,7 +945,7 @@ static void config_wakeups(void) last_abb_events = abb_events; } -void db8500_prcmu_enable_wakeups(u32 wakeups) +static void db8500_prcmu_enable_wakeups(u32 wakeups) { unsigned long flags; u32 bits; @@ -966,7 +966,7 @@ void db8500_prcmu_enable_wakeups(u32 wakeups) spin_unlock_irqrestore(&mb0_transfer.lock, flags); } -void db8500_prcmu_config_abb_event_readout(u32 abb_events) +static void db8500_prcmu_config_abb_event_readout(u32 abb_events) { unsigned long flags; @@ -978,7 +978,7 @@ void db8500_prcmu_config_abb_event_readout(u32 abb_events) spin_unlock_irqrestore(&mb0_transfer.lock, flags); } -void db8500_prcmu_get_abb_event_buffer(void __iomem **buf) +static void db8500_prcmu_get_abb_event_buffer(void __iomem **buf) { if (readb(tcdm_legacy_base + PRCM_ACK_MB0_READ_POINTER) & 1) *buf = (tcdm_legacy_base + PRCM_ACK_MB0_WAKEUP_1_4500); @@ -993,7 +993,7 @@ void db8500_prcmu_get_abb_event_buffer(void __iomem **buf) * * This function sets the the operating point of the ARM. */ -int db8500_prcmu_set_arm_opp(u8 opp) +static int db8500_prcmu_set_arm_opp(u8 opp) { int r; @@ -1028,7 +1028,7 @@ int db8500_prcmu_set_arm_opp(u8 opp) * * Returns: the current ARM OPP */ -int db8500_prcmu_get_arm_opp(void) +static int db8500_prcmu_get_arm_opp(void) { return readb(tcdm_legacy_base + PRCM_ACK_MB1_CURRENT_ARM_OPP); } @@ -1038,7 +1038,7 @@ int db8500_prcmu_get_arm_opp(void) * * Returns: the current DDR OPP */ -int db8500_prcmu_get_ddr_opp(void) +static int db8500_prcmu_get_ddr_opp(void) { return readb(PRCM_DDR_SUBSYS_APE_MINBW); } @@ -1050,7 +1050,7 @@ int db8500_prcmu_get_ddr_opp(void) * * This function sets the operating point of the DDR. */ -int db8500_prcmu_set_ddr_opp(u8 opp) +static int db8500_prcmu_set_ddr_opp(u8 opp) { if (opp < DDR_100_OPP || opp > DDR_25_OPP) return -EINVAL; @@ -1114,7 +1114,7 @@ unlock_and_return: * * This function sets the operating point of the APE. */ -int db8500_prcmu_set_ape_opp(u8 opp) +static int db8500_prcmu_set_ape_opp(u8 opp) { int r = 0; @@ -1161,18 +1161,18 @@ skip_message: * * Returns: the current APE OPP */ -int db8500_prcmu_get_ape_opp(void) +static int db8500_prcmu_get_ape_opp(void) { return readb(tcdm_legacy_base + PRCM_ACK_MB1_CURRENT_APE_OPP); } /** - * prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage + * db8500_prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage * @enable: true to request the higher voltage, false to drop a request. * * Calls to this function to enable and disable requests must be balanced. */ -int prcmu_request_ape_opp_100_voltage(bool enable) +static int db8500_prcmu_request_ape_opp_100_voltage(bool enable) { int r = 0; u8 header; @@ -1279,7 +1279,7 @@ static int request_pll(u8 clock, bool enable) * This function sets the state of a EPOD (power domain). It may not be called * from interrupt context. */ -int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state) +static int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state) { int r = 0; bool ram_retention = false; @@ -1341,11 +1341,11 @@ unlock_and_return: } /** - * prcmu_configure_auto_pm - Configure autonomous power management. + * db8500_prcmu_configure_auto_pm - Configure autonomous power management. * @sleep: Configuration for ApSleep. * @idle: Configuration for ApIdle. */ -void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, +static void db8500_prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, struct prcmu_auto_pm_config *idle) { u32 sleep_cfg; @@ -1386,7 +1386,6 @@ void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, spin_unlock_irqrestore(&mb2_transfer.auto_pm_lock, flags); } -EXPORT_SYMBOL(prcmu_configure_auto_pm); bool prcmu_is_auto_pm_enabled(void) { @@ -1701,7 +1700,7 @@ static unsigned long dsiescclk_rate(u8 n) return clock_rate(PRCMU_TVCLK) / max((u32)1, div); } -unsigned long prcmu_clock_rate(u8 clock) +static unsigned long db8500_prcmu_clock_rate(u8 clock) { if (clock < PRCMU_NUM_REG_CLOCKS) return clock_rate(clock); @@ -1850,7 +1849,7 @@ static long round_dsiescclk_rate(unsigned long rate) return rounded_rate; } -long prcmu_round_clock_rate(u8 clock, unsigned long rate) +static long db8500_prcmu_round_clock_rate(u8 clock, unsigned long rate) { if (clock < PRCMU_NUM_REG_CLOCKS) return round_clock_rate(clock, rate); @@ -1861,7 +1860,7 @@ long prcmu_round_clock_rate(u8 clock, unsigned long rate) else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) return round_dsiescclk_rate(rate); else - return (long)prcmu_clock_rate(clock); + return (long)db8500_prcmu_clock_rate(clock); } static void set_clock_rate(u8 clock, unsigned long rate) @@ -1989,7 +1988,7 @@ static void set_dsiescclk_rate(u8 n, unsigned long rate) writel(val, PRCM_DSITVCLK_DIV); } -int prcmu_set_clock_rate(u8 clock, unsigned long rate) +static int db8500_prcmu_set_clock_rate(u8 clock, unsigned long rate) { if (clock < PRCMU_NUM_REG_CLOCKS) set_clock_rate(clock, rate); @@ -2002,7 +2001,7 @@ int prcmu_set_clock_rate(u8 clock, unsigned long rate) return 0; } -int db8500_prcmu_config_esram0_deep_sleep(u8 state) +static int db8500_prcmu_config_esram0_deep_sleep(u8 state) { if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) || (state < ESRAM0_DEEP_SLEEP_STATE_OFF)) @@ -2122,7 +2121,7 @@ static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3) } -int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off) +static int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off) { BUG_ON(num == 0 || num > 0xf); return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0, @@ -2130,17 +2129,17 @@ int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off) A9WDOG_AUTO_OFF_DIS); } -int db8500_prcmu_enable_a9wdog(u8 id) +static int db8500_prcmu_enable_a9wdog(u8 id) { return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0); } -int db8500_prcmu_disable_a9wdog(u8 id) +static int db8500_prcmu_disable_a9wdog(u8 id) { return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0); } -int db8500_prcmu_kick_a9wdog(u8 id) +static int db8500_prcmu_kick_a9wdog(u8 id) { return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0); } @@ -2148,7 +2147,7 @@ int db8500_prcmu_kick_a9wdog(u8 id) /* * timeout is 28 bit, in ms. */ -int db8500_prcmu_load_a9wdog(u8 id, u32 timeout) +static int db8500_prcmu_load_a9wdog(u8 id, u32 timeout) { return prcmu_a9wdog(MB4H_A9WDOG_LOAD, (id & A9WDOG_ID_MASK) | @@ -2163,7 +2162,7 @@ int db8500_prcmu_load_a9wdog(u8 id, u32 timeout) } /** - * prcmu_abb_read() - Read register value(s) from the ABB. + * db8500_prcmu_abb_read() - Read register value(s) from the ABB. * @slave: The I2C slave address. * @reg: The (start) register address. * @value: The read out value(s). @@ -2172,7 +2171,7 @@ int db8500_prcmu_load_a9wdog(u8 id, u32 timeout) * Reads register value(s) from the ABB. * @size has to be 1 for the current firmware version. */ -int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) +static int db8500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) { int r; @@ -2211,7 +2210,7 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) } /** - * prcmu_abb_write_masked() - Write masked register value(s) to the ABB. + * db8500_prcmu_abb_write_masked() - Write masked register value(s) to the ABB. * @slave: The I2C slave address. * @reg: The (start) register address. * @value: The value(s) to write. @@ -2223,7 +2222,8 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) * will be written. The other bits are not changed. * @size has to be 1 for the current firmware version. */ -int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size) +static int db8500_prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, + u8 size) { int r; @@ -2259,7 +2259,7 @@ int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size) } /** - * prcmu_abb_write() - Write register value(s) to the ABB. + * db8500_prcmu_abb_write() - Write register value(s) to the ABB. * @slave: The I2C slave address. * @reg: The (start) register address. * @value: The value(s) to write. @@ -2268,7 +2268,7 @@ int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size) * Writes register value(s) to the ABB. * @size has to be 1 for the current firmware version. */ -int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) +static int db8500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) { u8 mask = ~0; @@ -2347,7 +2347,7 @@ unlock_and_return: mutex_unlock(&mb0_transfer.ac_wake_lock); } -bool db8500_prcmu_is_ac_wake_requested(void) +static bool db8500_prcmu_is_ac_wake_requested(void) { return (atomic_read(&ac_wake_req_state) != 0); } @@ -2358,7 +2358,7 @@ bool db8500_prcmu_is_ac_wake_requested(void) * Saves the reset reason code and then sets the APE_SOFTRST register which * fires interrupt to fw */ -void db8500_prcmu_system_reset(u16 reset_code) +static void db8500_prcmu_system_reset(u16 reset_code) { writew(reset_code, (tcdm_legacy_base + PRCM_SW_RST_REASON)); writel(1, PRCM_APE_SOFTRST); @@ -2370,7 +2370,7 @@ void db8500_prcmu_system_reset(u16 reset_code) * Retrieves the reset reason code stored by prcmu_system_reset() before * last restart. */ -u16 db8500_prcmu_get_reset_code(void) +static u16 db8500_prcmu_get_reset_code(void) { return readw(tcdm_legacy_base + PRCM_SW_RST_REASON); } @@ -2378,7 +2378,7 @@ u16 db8500_prcmu_get_reset_code(void) /** * db8500_prcmu_reset_modem - ask the PRCMU to reset modem */ -void db8500_prcmu_modem_reset(void) +static void db8500_prcmu_modem_reset(void) { mutex_lock(&mb1_transfer.lock); @@ -2651,6 +2651,202 @@ static char *fw_project_name(u8 project) } } +static inline void db8500_prcmu_set(unsigned int reg, u32 bits) +{ + db8500_prcmu_write_masked(reg, bits, bits); +} + +static inline void db8500_prcmu_clear(unsigned int reg, u32 bits) +{ + db8500_prcmu_write_masked(reg, bits, 0); +} + + +static int db8500_prcmu_enable_spi2(void) +{ + db8500_prcmu_set(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT); + return 0; +} + +/** + * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1. + */ +static int db8500_prcmu_disable_spi2(void) +{ + db8500_prcmu_clear(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT); + return 0; +} + +/** + * prcmu_enable_stm_mod_uart - Enables pin muxing for STMMOD + * and UARTMOD on OtherAlternateC3. + */ +static int db8500_prcmu_enable_stm_mod_uart(void) +{ + db8500_prcmu_set(DB8500_PRCM_GPIOCR, + (DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 | + DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0)); + return 0; +} + +/** + * prcmu_disable_stm_mod_uart - Disables pin muxing for STMMOD + * and UARTMOD on OtherAlternateC3. + */ +static int db8500_prcmu_disable_stm_mod_uart(void) +{ + db8500_prcmu_clear(DB8500_PRCM_GPIOCR, + (DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 | + DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0)); + return 0; +} + +/** + * prcmu_enable_stm_ape - Enables pin muxing for STM APE on OtherAlternateC1. + */ +static int db8500_prcmu_enable_stm_ape(void) +{ + db8500_prcmu_set(DB8500_PRCM_GPIOCR, + DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD); + return 0; +} + +/** + * prcmu_disable_stm_ape - Disables pin muxing for STM APE on OtherAlternateC1. + */ +static int db8500_prcmu_disable_stm_ape(void) +{ + db8500_prcmu_clear(DB8500_PRCM_GPIOCR, + DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD); + return 0; +} + +static struct prcmu_val_data db8500_val_tab[] = { + { + .val = APE_OPP, + .set_val = db8500_prcmu_set_ape_opp, + .get_val = db8500_prcmu_get_ape_opp, + }, + { + .val = DDR_OPP, + .set_val = db8500_prcmu_set_ddr_opp, + .get_val = db8500_prcmu_get_ddr_opp, + }, + { + .val = ARM_OPP, + .set_val = db8500_prcmu_set_arm_opp, + .get_val = db8500_prcmu_get_arm_opp, + } +}; +static struct prcmu_out_data db8500_out_tab[] = { + { + .out = SPI2_MUX, + .enable = db8500_prcmu_enable_spi2, + .disable = db8500_prcmu_disable_spi2, + }, + { + .out = STM_APE_MUX, + .enable = db8500_prcmu_enable_stm_ape, + .disable = db8500_prcmu_disable_stm_ape, + }, + { + .out = STM_MOD_UART_MUX, + .enable = db8500_prcmu_enable_stm_mod_uart, + .disable = db8500_prcmu_disable_stm_mod_uart, + } +}; + +static struct prcmu_early_data db8500_early_fops = { + /* system reset */ + .system_reset = db8500_prcmu_system_reset, + + /* clock service */ + .config_clkout = db8500_prcmu_config_clkout, + .request_clock = db8500_prcmu_request_clock, + + /* direct register access */ + .read = db8500_prcmu_read, + .write = db8500_prcmu_write, + .write_masked = db8500_prcmu_write_masked, + /* others */ + .round_clock_rate = db8500_prcmu_round_clock_rate, + .set_clock_rate = db8500_prcmu_set_clock_rate, + .clock_rate = db8500_prcmu_clock_rate, + .get_fw_version = db8500_prcmu_get_fw_version, + .has_arm_maxopp = db8500_prcmu_has_arm_maxopp, +}; + +static struct prcmu_fops_register db8500_early_tab[] = { + { + .fops = PRCMU_EARLY, + .data.pearly = &db8500_early_fops + }, + { + .fops = PRCMU_VAL, + .size = ARRAY_SIZE(db8500_val_tab), + .data.pval = db8500_val_tab + }, + { + .fops = PRCMU_OUT, + .size = ARRAY_SIZE(db8500_out_tab), + .data.pout = db8500_out_tab + } +}; + +static struct prcmu_fops_register_data db8500_early_data = { + .size = ARRAY_SIZE(db8500_early_tab), + .tab = db8500_early_tab +}; + +struct prcmu_probe_data db8500_probe_fops = { + /* sysfs soc inf */ + .get_reset_code = db8500_prcmu_get_reset_code, + + /* pm/suspend.c/cpu freq */ + .config_esram0_deep_sleep = db8500_prcmu_config_esram0_deep_sleep, + .set_power_state = db8500_prcmu_set_power_state, + .get_power_state_result = db8500_prcmu_get_power_state_result, + .enable_wakeups = db8500_prcmu_enable_wakeups, + .is_ac_wake_requested = db8500_prcmu_is_ac_wake_requested, + + /* modem */ + .modem_reset = db8500_prcmu_modem_reset, + + /* no used at all */ + .config_abb_event_readout = db8500_prcmu_config_abb_event_readout, + .get_abb_event_buffer = db8500_prcmu_get_abb_event_buffer, + + /* abb access */ + .abb_read = db8500_prcmu_abb_read, + .abb_write = db8500_prcmu_abb_write, + /* other u8500 specific */ + .request_ape_opp_100_voltage = db8500_prcmu_request_ape_opp_100_voltage, + .configure_auto_pm = db8500_prcmu_configure_auto_pm, + .set_epod = db8500_prcmu_set_epod, + + /* abb specific access */ + .abb_write_masked = db8500_prcmu_abb_write_masked, + + /* watchdog */ + .config_a9wdog = db8500_prcmu_config_a9wdog, + .enable_a9wdog = db8500_prcmu_enable_a9wdog, + .disable_a9wdog = db8500_prcmu_disable_a9wdog, + .kick_a9wdog = db8500_prcmu_kick_a9wdog, + .load_a9wdog = db8500_prcmu_load_a9wdog, +}; + +static struct prcmu_fops_register db8500_probe_tab[] = { + { + .fops = PRCMU_PROBE, + .data.pprobe = &db8500_probe_fops, + }, +}; + +struct prcmu_fops_register_data db8500_probe_data = { + .size = ARRAY_SIZE(db8500_probe_tab), + .tab = db8500_probe_tab, +}; + static int db8500_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hwirq) { @@ -2680,7 +2876,8 @@ static int db8500_irq_init(struct device_node *np) return 0; } -void __init db8500_prcmu_early_init(struct prcmu_tcdm_map *map) +struct prcmu_fops_register_data *__init + db8500_prcmu_early_init(struct prcmu_tcdm_map *map) { void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K); @@ -2720,6 +2917,9 @@ void __init db8500_prcmu_early_init(struct prcmu_tcdm_map *map) init_completion(&mb5_transfer.work); INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work); + + /* early init of dbx500-prcmu */ + return &db8500_early_data; } static void __init init_prcm_registers(void) @@ -2976,6 +3176,11 @@ static struct resource ab8500_resources[] = { static struct mfd_cell db8500_prcmu_devs[] = { { + .name = "dbx500-prcmu", + .platform_data = &db8500_probe_data, + .pdata_size = sizeof(db8500_probe_data), + }, + { .name = "db8500-prcmu-regulators", .of_compatible = "stericsson,db8500-prcmu-regulator", .platform_data = &db8500_regulators, @@ -2996,6 +3201,11 @@ static struct mfd_cell db8500_prcmu_devs[] = { static struct mfd_cell db9540_prcmu_devs[] = { { + .name = "dbx500-prcmu", + .platform_data = &db8500_probe_data, + .pdata_size = sizeof(db8500_probe_data), + }, + { .name = "db8500-prcmu-regulators", .of_compatible = "stericsson,db8500-prcmu-regulator", .platform_data = &db8500_regulators, @@ -3048,12 +3258,13 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) { if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) { db8500_prcmu_devs[i].platform_data = ab8500_platdata; - db8500_prcmu_devs[i].pdata_size = sizeof(struct ab8500_platform_data); + db8500_prcmu_devs[i].pdata_size = + sizeof(struct ab8500_platform_data); } } if (cpu_is_u8500v20_or_later() && !cpu_is_u9540()) - prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); + db8500_prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); if (cpu_is_u9540()) err = mfd_add_devices(&pdev->dev, 0, db9540_prcmu_devs, diff --git a/drivers/mfd/dbx500-prcmu.c b/drivers/mfd/dbx500-prcmu.c new file mode 100644 index 0000000..1823ab7 --- /dev/null +++ b/drivers/mfd/dbx500-prcmu.c @@ -0,0 +1,813 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + * + * Author: Michel Jaouen for + * ST-Ericsson. + * License terms: GNU Gereral Public License (GPL) version 2 + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define dbx500_prcmu_warn(a) \ + pr_warn("%s : dbx500-prcmu driver %s", \ + __func__, a); + +#define dbx500_prcmu_error(a) \ + pr_err("%s : dbx500-prcmu driver %s", \ + __func__, a); + +#define dbx500_prcmu_early_trap_void \ + pr_err("%s called :dbx500-prcmu driver not initialized",\ + __func__); \ + +#define dbx500_prcmu_early_trap(a) do { \ + pr_err("%s called :dbx500-prcmu driver not initialized",\ + __func__); \ + return a; \ + } while (0) + +#define dbx500_prcmu_trap(a) do { \ + pr_err("%s called : dbx500-prcmu driver not probed", \ + __func__); \ + return a; \ + } while (0) + +#define dbx500_prcmu_trap_void \ + pr_err("%s called : dbx500-prcmu driver not probed", \ + __func__); + +/* dummy handler */ + +static int dummy_set_power_state(u8 state, bool keep_ulp_clk, + bool keep_ap_pll) { + dbx500_prcmu_trap(-EINVAL); +} + +static u8 dummy_get_power_state_result(void) +{ + dbx500_prcmu_trap(-EINVAL); +} + +static int dummy_config_clkout(u8 clkout, u8 source, u8 div) +{ + dbx500_prcmu_early_trap(-EINVAL); +} + +static int dummy_request_clock(u8 clock, bool enable) +{ + dbx500_prcmu_early_trap(-EINVAL); +} + +static long dummy_round_clock_rate(u8 clock, unsigned long rate) +{ + dbx500_prcmu_early_trap(-EINVAL); +} + +static int dummy_set_clock_rate(u8 clock, unsigned long rate) +{ + dbx500_prcmu_early_trap(-EINVAL); +} + +static unsigned long dummy_clock_rate(u8 clock) +{ + dbx500_prcmu_early_trap(-EINVAL); +} + +static int dummy_set_val(enum prcmu_val type, u8 value) +{ + dbx500_prcmu_early_trap(-EINVAL); +} + +static int dummy_get_val(enum prcmu_val type) +{ + dbx500_prcmu_early_trap(-EINVAL); +} + +static void dummy_system_reset(u16 reset_code) +{ + dbx500_prcmu_early_trap_void; +} +static u16 dummy_get_reset_code(void) +{ + dbx500_prcmu_trap(-EINVAL); +} +static u32 dummy_get_reset_status(void) +{ + dbx500_prcmu_trap(-EINVAL); +} + +static void dummy_enable_wakeups(u32 wakeups) +{ + dbx500_prcmu_trap_void; +} + +static bool dummy_is_ac_wake_requested(void) +{ + dbx500_prcmu_trap(false); +} + +static int dummy_disable(enum prcmu_out out) +{ + dbx500_prcmu_early_trap(-EINVAL); +} + +static int dummy_enable(enum prcmu_out out) +{ + dbx500_prcmu_early_trap(-EINVAL); +} + +static u32 dummy_read(unsigned int reg) +{ + dbx500_prcmu_early_trap(-EINVAL); +} + +static void dummy_write(unsigned int reg, u32 value) +{ + dbx500_prcmu_early_trap_void; +} + +static void default_write_masked(unsigned int reg, u32 mask, u32 value) +{ + u32 val; + val = readl(_PRCMU_BASE + reg); + val = ((val & ~mask) | (value & mask)); + writel(val, (_PRCMU_BASE + reg)); +} + +static int dummy_config_esram0_deep_sleep(u8 state) +{ + dbx500_prcmu_trap(-EINVAL); +} + +static void dummy_config_abb_event_readout(u32 abb_events) +{ + dbx500_prcmu_trap_void; +} + +static void dummy_get_abb_event_buffer(void __iomem **buf) +{ + dbx500_prcmu_trap_void; +} + +static int dummy_abb_read(u8 slave, u8 reg, u8 *value, u8 size) +{ + dbx500_prcmu_trap(-EINVAL); +} + +static int dummy_abb_write(u8 slave, u8 reg, u8 *value, u8 size) +{ + dbx500_prcmu_trap(-EINVAL); +} + +static int dummy_abb_write_masked(u8 slave, u8 reg, u8 *value, + u8 *mask, u8 size) +{ + dbx500_prcmu_trap(-EINVAL); +} + +static void dummy_modem_reset(void) +{ + dbx500_prcmu_trap_void; +} + +static bool dummy_has_arm_maxopp(void) +{ + dbx500_prcmu_early_trap(-EINVAL); +} + +static struct prcmu_fw_version *dummy_get_fw_version(void) +{ + dbx500_prcmu_early_trap(NULL); +} + +static int dummy_request_ape_opp_100_voltage(bool enable) +{ + dbx500_prcmu_trap(-EINVAL); +} + +static void dummy_configure_auto_pm(struct prcmu_auto_pm_config *sleep, + struct prcmu_auto_pm_config *idle) +{ + dbx500_prcmu_trap_void; +} + +static int dummy_config_a9wdog(u8 num, bool sleep_auto_off) +{ + dbx500_prcmu_trap(-EINVAL); +} + +static int dummy_enable_a9wdog(u8 id) +{ + dbx500_prcmu_trap(-EINVAL); +} + +static int dummy_disable_a9wdog(u8 id) +{ + dbx500_prcmu_trap(-EINVAL); +} + +static int dummy_kick_a9wdog(u8 id) +{ + dbx500_prcmu_trap(-EINVAL); +} + +static int dummy_load_a9wdog(u8 id, u32 timeout) +{ + dbx500_prcmu_trap(-EINVAL); +} + +struct prcmu_probe_data dummy_fops = { + /* sysfs soc inf */ + .get_reset_code = dummy_get_reset_code, + + /* pm/suspend.c/cpu freq */ + .config_esram0_deep_sleep = dummy_config_esram0_deep_sleep, + .set_power_state = dummy_set_power_state, + .get_power_state_result = dummy_get_power_state_result, + .enable_wakeups = dummy_enable_wakeups, + .is_ac_wake_requested = dummy_is_ac_wake_requested, + + /* modem */ + .modem_reset = dummy_modem_reset, + + /* no used at all */ + .config_abb_event_readout = dummy_config_abb_event_readout, + .get_abb_event_buffer = dummy_get_abb_event_buffer, + + /* abb access */ + .abb_read = dummy_abb_read, + .abb_write = dummy_abb_write, + .get_reset_status = dummy_get_reset_status, + /* other u8500 specific */ + .request_ape_opp_100_voltage = dummy_request_ape_opp_100_voltage, + .configure_auto_pm = dummy_configure_auto_pm, + + /* abb specific access */ + .abb_write_masked = dummy_abb_write_masked, + + /* watchdog */ + .config_a9wdog = dummy_config_a9wdog, + .enable_a9wdog = dummy_enable_a9wdog, + .disable_a9wdog = dummy_disable_a9wdog, + .kick_a9wdog = dummy_kick_a9wdog, + .load_a9wdog = dummy_load_a9wdog, +}; + +static struct prcmu_early_data default_early_fops = { + /* system reset */ + .system_reset = dummy_system_reset, + + /* clock service */ + .config_clkout = dummy_config_clkout, + .request_clock = dummy_request_clock, + + /* direct register access */ + .read = dummy_read, + .write = dummy_write, + .write_masked = default_write_masked, + /* others */ + .round_clock_rate = dummy_round_clock_rate, + .set_clock_rate = dummy_set_clock_rate, + .clock_rate = dummy_clock_rate, + .get_fw_version = dummy_get_fw_version, + .has_arm_maxopp = dummy_has_arm_maxopp, +}; + +static struct { + struct prcmu_early_data *pearly; + struct prcmu_probe_data *pprobe; + struct prcmu_probe_cpuhp_data *pprobe_cpuhp; + struct prcmu_val_data tab_val[PRCMU_VAL_MAX]; + int (*set_val)(enum prcmu_val type, u8 val); + int (*get_val) (enum prcmu_val type); + struct prcmu_out_data tab_out[PRCMU_OUT_MAX]; + int (*disable) (enum prcmu_out out); + int (*enable) (enum prcmu_out out); + bool (*check_ape_age)(void); +} dbx500_prcmu_context = { + .pearly = &default_early_fops, + .pprobe = &dummy_fops, + .set_val = dummy_set_val, + .get_val = dummy_get_val, + .disable = dummy_disable, + .enable = dummy_enable, +}; + +/* early service */ + +struct prcmu_fw_version *prcmu_get_fw_version(void) +{ + return dbx500_prcmu_context.pearly->get_fw_version(); +} + +bool prcmu_has_arm_maxopp(void) +{ + return dbx500_prcmu_context.pearly->has_arm_maxopp(); +} + +void prcmu_system_reset(u16 reset_code) +{ + dbx500_prcmu_context.pearly->system_reset(reset_code); +} + +u32 prcmu_read(unsigned int reg) +{ + return dbx500_prcmu_context.pearly->read(reg); +} + +void prcmu_write(unsigned int reg, u32 value) +{ + return dbx500_prcmu_context.pearly->write(reg, value); +} + +void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) +{ + dbx500_prcmu_context.pearly->write_masked(reg, mask, value); +} + +int prcmu_config_clkout(u8 clkout, u8 source, u8 div) +{ + return dbx500_prcmu_context.pearly->config_clkout(clkout, source, div); +} + +int prcmu_request_clock(u8 clock, bool enable) +{ + return dbx500_prcmu_context.pearly->request_clock(clock, enable); +} + +unsigned long prcmu_clock_rate(u8 clock) +{ + return dbx500_prcmu_context.pearly->clock_rate(clock); +} + +long prcmu_round_clock_rate(u8 clock, unsigned long rate) +{ + return dbx500_prcmu_context.pearly->round_clock_rate(clock, rate); +} + +int prcmu_set_clock_rate(u8 clock, unsigned long rate) +{ + return dbx500_prcmu_context.pearly->set_clock_rate(clock, rate); +} + +int prcmu_set_val(enum prcmu_val type, u32 value) +{ + return dbx500_prcmu_context.set_val(type, value); +} + +int prcmu_get_val(enum prcmu_val type) +{ + return dbx500_prcmu_context.get_val(type); +} + +int prcmu_enable_out(enum prcmu_out out) +{ + return dbx500_prcmu_context.enable(out); +} + +int prcmu_disable_out(enum prcmu_out out) +{ + return dbx500_prcmu_context.disable(out); +} + +int prcmu_set_ddr_opp(u8 opp) +{ + return dbx500_prcmu_context.set_val(DDR_OPP, opp); +} + +int prcmu_get_ddr_opp(void) +{ + return dbx500_prcmu_context.get_val(DDR_OPP); +} + +int prcmu_set_arm_opp(u8 opp) +{ + return dbx500_prcmu_context.set_val(ARM_OPP, opp); +} + +int prcmu_get_arm_opp(void) +{ + return dbx500_prcmu_context.get_val(ARM_OPP); +} + +int prcmu_set_ape_opp(u8 opp) +{ + return dbx500_prcmu_context.set_val(APE_OPP, opp); +} + +int prcmu_get_ape_opp(void) +{ + return dbx500_prcmu_context.get_val(APE_OPP); +} + +int prcmu_gic_decouple(void) +{ + return db8500_prcmu_gic_decouple(); +} +int prcmu_gic_recouple(void) +{ + return db8500_prcmu_gic_recouple(); +} +bool prcmu_gic_pending_irq(void) +{ + return db8500_prcmu_gic_pending_irq(); +} + +bool prcmu_is_cpu_in_wfi(int cpu) +{ + return db8500_prcmu_is_cpu_in_wfi(cpu); +} + +int prcmu_copy_gic_settings(void) +{ + return db8500_prcmu_copy_gic_settings(); +} + +bool prcmu_pending_irq(void) +{ + return db8500_prcmu_pending_irq(); +} + +/* other service available after the probe */ + +int prcmu_set_power_state(u8 state, bool keep_ulp_clk, + bool keep_ap_pll) +{ + return dbx500_prcmu_context.pprobe->set_power_state(state, + keep_ulp_clk, + keep_ap_pll); +} + +u8 prcmu_get_power_state_result(void) +{ + return dbx500_prcmu_context.pprobe->get_power_state_result(); +} + +void prcmu_enable_wakeups(u32 wakeups) +{ + dbx500_prcmu_context.pprobe->enable_wakeups(wakeups); +} + +void prcmu_disable_wakeups(void) +{ + dbx500_prcmu_context.pprobe->enable_wakeups(0); +} + +void prcmu_config_abb_event_readout(u32 abb_events) +{ + dbx500_prcmu_context.pprobe->config_abb_event_readout(abb_events); +} + +void prcmu_get_abb_event_buffer(void __iomem **buf) +{ + dbx500_prcmu_context.pprobe->get_abb_event_buffer(buf); +} + +u16 prcmu_get_reset_code(void) +{ + return dbx500_prcmu_context.pprobe->get_reset_code(); +} + +void prcmu_modem_reset(void) +{ + dbx500_prcmu_context.pprobe->modem_reset(); +} + +int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) +{ + return dbx500_prcmu_context.pprobe->abb_read(slave, reg, value, size); +} + +int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) +{ + return dbx500_prcmu_context.pprobe->abb_write(slave, reg, value, size); +} + +int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, + u8 *mask, u8 size) +{ + return dbx500_prcmu_context.pprobe->abb_write_masked( + slave, reg, value, mask, size); +} + +u32 prcmu_get_reset_status(void) +{ + return dbx500_prcmu_context.pprobe->get_reset_status(); +} + +bool prcmu_is_ac_wake_requested(void) +{ + return dbx500_prcmu_context.pprobe->is_ac_wake_requested(); +} + +int prcmu_config_esram0_deep_sleep(u8 state) +{ + return dbx500_prcmu_context.pprobe->config_esram0_deep_sleep(state); +} + +int prcmu_set_epod(u16 epod_id, u8 epod_state) +{ + return dbx500_prcmu_context.pprobe->set_epod(epod_id, epod_state); +} + +/** + * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1. + */ +void prcmu_enable_spi2(void) +{ + dbx500_prcmu_context.enable(SPI2_MUX); +} + +/** + * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1. + */ +void prcmu_disable_spi2(void) +{ + dbx500_prcmu_context.disable(SPI2_MUX); +} + +/** + * prcmu_enable_stm_mod_uart - Enables pin muxing for STMMOD + * and UARTMOD on OtherAlternateC3. + */ +void prcmu_enable_stm_mod_uart(void) +{ + dbx500_prcmu_context.enable(STM_MOD_UART_MUX); +} + +/** + * prcmu_disable_stm_mod_uart - Disables pin muxing for STMMOD + * and UARTMOD on OtherAlternateC3. + */ +void prcmu_disable_stm_mod_uart(void) +{ + dbx500_prcmu_context.disable(STM_MOD_UART_MUX); +} + +/** + * prcmu_enable_stm_ape - Enables pin muxing for STM APE on OtherAlternateC1. + */ +void prcmu_enable_stm_ape(void) +{ + dbx500_prcmu_context.enable(STM_APE_MUX); +} + +/** + * prcmu_disable_stm_ape - Disables pin muxing for STM APE on OtherAlternateC1. + */ +void prcmu_disable_stm_ape(void) +{ + dbx500_prcmu_context.disable(STM_APE_MUX); +} + +void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, + struct prcmu_auto_pm_config *idle) +{ + dbx500_prcmu_context.pprobe->configure_auto_pm(sleep, idle); +} +EXPORT_SYMBOL(prcmu_configure_auto_pm); + +int prcmu_request_ape_opp_100_voltage(bool enable) +{ + return dbx500_prcmu_context. + pprobe->request_ape_opp_100_voltage(enable); +} + +static int dbx500_prcmu_set_val(enum prcmu_val type, u8 value) +{ + if (type < PRCMU_VAL_MAX) + return dbx500_prcmu_context.tab_val[type].set_val(value); + dbx500_prcmu_error("request out of range"); + return -EIO; + +} + +static int dbx500_prcmu_get_val(enum prcmu_val type) +{ + if (type < PRCMU_VAL_MAX) + return dbx500_prcmu_context.tab_val[type].get_val(); + dbx500_prcmu_error("request out of range"); + return -EIO; + +} + +static int dbx500_prcmu_enable_out(enum prcmu_out out) +{ + if (out < PRCMU_OUT_MAX) + return dbx500_prcmu_context.tab_out[out].enable(); + dbx500_prcmu_error("request out of range"); + return -EIO; +} + +static int dbx500_prcmu_disable_out(enum prcmu_out out) +{ + if (out < PRCMU_OUT_MAX) + return dbx500_prcmu_context.tab_out[out].disable(); + dbx500_prcmu_error("request out of range"); + return -EIO; +} + +/* used for enable , disable and get */ +static int dbx500_default_handler(void) +{ + return 0; +} +static int dbx500_default_set(u8 val) +{ + return 0; +} +static int default_get_ape_opp(void) +{ + return APE_100_OPP; +} + + +static int default_get_ddr_opp(void) +{ + return DDR_100_OPP; +} + +static struct prcmu_val_data default_ape = { + .set_val = dbx500_default_set, + .get_val = default_get_ape_opp, +}; + + +static struct prcmu_val_data default_ddr = { + .set_val = dbx500_default_set, + .get_val = default_get_ddr_opp, +}; + +static struct prcmu_out_data default_out = { + .enable = dbx500_default_handler, + .disable = dbx500_default_handler, +}; + +static struct prcmu_val_data default_val = { + .set_val = dbx500_default_set, + .get_val = dbx500_default_handler, +}; + +static void dbx500_prcmu_init_ctx(void) +{ + int i; + struct prcmu_val_data *pdefault; + for (i = 0; i < PRCMU_VAL_MAX; i++) { + switch (i) { + case DDR_OPP: + pdefault = &default_ddr; + break; + case APE_OPP: + pdefault = &default_ape; + break; + default: + pdefault = &default_val; + } + + memcpy(&dbx500_prcmu_context.tab_val[i], pdefault, + sizeof(struct prcmu_val_data)); + } + + for (i = 0; i < PRCMU_OUT_MAX; i++) + memcpy(&dbx500_prcmu_context.tab_out[i], &default_out, + sizeof(struct prcmu_out_data)); + dbx500_prcmu_context.enable = dbx500_prcmu_enable_out; + dbx500_prcmu_context.disable = dbx500_prcmu_disable_out; + dbx500_prcmu_context.set_val = dbx500_prcmu_set_val; + dbx500_prcmu_context.get_val = dbx500_prcmu_get_val; +} + +static void dbx500_prcmu_register_pout(struct prcmu_out_data *data, int size) +{ + int i; + for (i = 0; i < size; i++) + if (data[i].out < PRCMU_OUT_MAX) + memcpy(&dbx500_prcmu_context.tab_out[data[i].out], + &data[i], sizeof(struct prcmu_out_data)); + else + dbx500_prcmu_error("ops out of range"); +} + +static void dbx500_prcmu_register_pval(struct prcmu_val_data *data, int size) +{ + int i; + for (i = 0; i < size; i++) + if (data[i].val < PRCMU_VAL_MAX) + memcpy(&dbx500_prcmu_context.tab_val[data[i].val], + &data[i], sizeof(struct prcmu_val_data)); + else + dbx500_prcmu_error("registering ops out of range"); +} + +/** + * @brief register prcmu handler + * + * @param fops + */ +void __init prcmu_early_init(struct prcmu_tcdm_map *map) +{ + int i, ret = 0; + struct prcmu_fops_register_data *data; + + data = db8500_prcmu_early_init(map); + + if (data == NULL) + return; + + dbx500_prcmu_init_ctx(); + + for (i = 0; i < data->size; i++) { + switch (data->tab[i].fops) { + case PRCMU_EARLY: + dbx500_prcmu_context.pearly = data->tab[i].data.pearly; + break; + case PRCMU_VAL: + dbx500_prcmu_register_pval(data->tab[i].data.pval, + data->tab[i].size); + break; + case PRCMU_OUT: + dbx500_prcmu_register_pout(data->tab[i].data.pout, + data->tab[i].size); + break; + default: + dbx500_prcmu_error("ops out of range"); + ret = -EIO; + } + } + return; +} + +/** + * @brief dbx500-prcmu probe function + * + * @param pdev + * + * @return + */ +static int __devinit dbx500_prcmu_probe(struct platform_device *pdev) +{ + struct prcmu_fops_register_data *data = dev_get_platdata(&pdev->dev); + int i, ret = 0; + for (i = 0; i < data->size; i++) { + switch (data->tab[i].fops) { + case PRCMU_VAL: + dbx500_prcmu_register_pval(data->tab[i].data.pval, + data->tab[i].size); + break; + case PRCMU_OUT: + dbx500_prcmu_register_pout(data->tab[i].data.pout, + data->tab[i].size); + break; + case PRCMU_PROBE: + dbx500_prcmu_context.pprobe = + data->tab[i].data.pprobe; + break; + case PRCMU_PROBE_CPU_HP: + dbx500_prcmu_context.pprobe_cpuhp = + data->tab[i].data.pprobe_cpuhp; + break; + default: + dbx500_prcmu_error("ops out of range"); + ret = -EIO; + } + } + return ret; +} + +/* No action required in suspend/resume, thus the lack of functions */ +static struct platform_driver dbx500_prcmu_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "dbx500-prcmu", + }, + .probe = dbx500_prcmu_probe, +}; + +static int __init dbx500_prcmu_init(void) +{ + return platform_driver_register(&dbx500_prcmu_driver); +} + +MODULE_AUTHOR("Michel JAOUEN "); +MODULE_DESCRIPTION("DBX500 PRCMU DRIVER"); +MODULE_LICENSE("GPL"); + +core_initcall(dbx500_prcmu_init); + diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h index f932a56..a6d7298 100644 --- a/include/linux/mfd/db8500-prcmu.h +++ b/include/linux/mfd/db8500-prcmu.h @@ -140,29 +140,6 @@ enum ap_pwrst { }; /** - * enum ap_pwrst_trans - Transition states defined in PRCMU firmware - * @NO_TRANSITION: No power state transition - * @APEXECUTE_TO_APSLEEP: Power state transition from ApExecute to ApSleep - * @APIDLE_TO_APSLEEP: Power state transition from ApIdle to ApSleep - * @APBOOT_TO_APEXECUTE: Power state transition from ApBoot to ApExecute - * @APEXECUTE_TO_APDEEPSLEEP: Power state transition from ApExecute to - * ApDeepSleep - * @APEXECUTE_TO_APIDLE: Power state transition from ApExecute to ApIdle - */ -enum ap_pwrst_trans { - PRCMU_AP_NO_CHANGE = 0x00, - APEXECUTE_TO_APSLEEP = 0x01, - APIDLE_TO_APSLEEP = 0x02, /* To be removed */ - PRCMU_AP_SLEEP = 0x01, - APBOOT_TO_APEXECUTE = 0x03, - APEXECUTE_TO_APDEEPSLEEP = 0x04, /* To be removed */ - PRCMU_AP_DEEP_SLEEP = 0x04, - APEXECUTE_TO_APIDLE = 0x05, /* To be removed */ - PRCMU_AP_IDLE = 0x05, - PRCMU_AP_DEEP_IDLE = 0x07, -}; - -/** * enum hw_acc_state - State definition for hardware accelerator * @HW_NO_CHANGE: The hardware accelerator state must remain unchanged * @HW_OFF: The hardware accelerator must be switched off @@ -509,71 +486,41 @@ struct prcmu_fw_version { #ifdef CONFIG_MFD_DB8500_PRCMU -void db8500_prcmu_early_init(struct prcmu_tcdm_map *map); +struct prcmu_fops_register_data *db8500_prcmu_early_init( + struct prcmu_tcdm_map *map); int prcmu_set_rc_a2p(enum romcode_write); enum romcode_read prcmu_get_rc_p2a(void); enum ap_pwrst prcmu_get_xp70_current_state(void); -bool prcmu_has_arm_maxopp(void); -struct prcmu_fw_version *prcmu_get_fw_version(void); -int prcmu_request_ape_opp_100_voltage(bool enable); + int prcmu_release_usb_wakeup_state(void); -void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, - struct prcmu_auto_pm_config *idle); -bool prcmu_is_auto_pm_enabled(void); -int prcmu_config_clkout(u8 clkout, u8 source, u8 div); -int prcmu_set_clock_divider(u8 clock, u8 divider); int db8500_prcmu_config_hotdog(u8 threshold); int db8500_prcmu_config_hotmon(u8 low, u8 high); int db8500_prcmu_start_temp_sense(u16 cycles32k); int db8500_prcmu_stop_temp_sense(void); -int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); -int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); + int prcmu_ac_wake_req(void); void prcmu_ac_sleep_req(void); -void db8500_prcmu_modem_reset(void); - -int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off); -int db8500_prcmu_enable_a9wdog(u8 id); -int db8500_prcmu_disable_a9wdog(u8 id); -int db8500_prcmu_kick_a9wdog(u8 id); -int db8500_prcmu_load_a9wdog(u8 id, u32 val); -void db8500_prcmu_system_reset(u16 reset_code); -int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll); -u8 db8500_prcmu_get_power_state_result(void); int db8500_prcmu_gic_decouple(void); int db8500_prcmu_gic_recouple(void); int db8500_prcmu_copy_gic_settings(void); bool db8500_prcmu_gic_pending_irq(void); bool db8500_prcmu_pending_irq(void); bool db8500_prcmu_is_cpu_in_wfi(int cpu); -void db8500_prcmu_enable_wakeups(u32 wakeups); -int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state); -int db8500_prcmu_request_clock(u8 clock, bool enable); + int db8500_prcmu_set_display_clocks(void); int db8500_prcmu_disable_dsipll(void); int db8500_prcmu_enable_dsipll(void); -void db8500_prcmu_config_abb_event_readout(u32 abb_events); -void db8500_prcmu_get_abb_event_buffer(void __iomem **buf); -int db8500_prcmu_config_esram0_deep_sleep(u8 state); -u16 db8500_prcmu_get_reset_code(void); -bool db8500_prcmu_is_ac_wake_requested(void); -int db8500_prcmu_set_arm_opp(u8 opp); -int db8500_prcmu_get_arm_opp(void); -int db8500_prcmu_set_ape_opp(u8 opp); -int db8500_prcmu_get_ape_opp(void); -int db8500_prcmu_set_ddr_opp(u8 opp); -int db8500_prcmu_get_ddr_opp(void); - -u32 db8500_prcmu_read(unsigned int reg); -void db8500_prcmu_write(unsigned int reg, u32 value); -void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value); #else /* !CONFIG_MFD_DB8500_PRCMU */ -static inline void db8500_prcmu_early_init(struct prcmu_tcdm_map *map) {} +static struct prcmu_fops_register_data *db8500_prcmu_early_init( + struct prcmu_tcdm_map *map) +{ + return NULL; +} static inline int prcmu_set_rc_a2p(enum romcode_write code) { @@ -590,66 +537,12 @@ static inline enum ap_pwrst prcmu_get_xp70_current_state(void) return AP_EXECUTE; } -static inline bool prcmu_has_arm_maxopp(void) -{ - return false; -} - -static inline struct prcmu_fw_version *prcmu_get_fw_version(void) -{ - return NULL; -} - -static inline int db8500_prcmu_set_ape_opp(u8 opp) -{ - return 0; -} - -static inline int db8500_prcmu_get_ape_opp(void) -{ - return APE_100_OPP; -} - -static inline int prcmu_request_ape_opp_100_voltage(bool enable) -{ - return 0; -} - -static inline int prcmu_release_usb_wakeup_state(void) -{ - return 0; -} - -static inline int db8500_prcmu_set_ddr_opp(u8 opp) -{ - return 0; -} - -static inline int db8500_prcmu_get_ddr_opp(void) -{ - return DDR_100_OPP; -} - -static inline void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, - struct prcmu_auto_pm_config *idle) -{ -} static inline bool prcmu_is_auto_pm_enabled(void) { return false; } -static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div) -{ - return 0; -} - -static inline int prcmu_set_clock_divider(u8 clock, u8 divider) -{ - return 0; -} - static inline int db8500_prcmu_config_hotdog(u8 threshold) { return 0; @@ -670,129 +563,6 @@ static inline int db8500_prcmu_stop_temp_sense(void) return 0; } -static inline int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) -{ - return -ENOSYS; -} - -static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) -{ - return -ENOSYS; -} - -static inline int prcmu_ac_wake_req(void) -{ - return 0; -} - -static inline void prcmu_ac_sleep_req(void) {} - -static inline void db8500_prcmu_modem_reset(void) {} - -static inline void db8500_prcmu_system_reset(u16 reset_code) {} - -static inline int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, - bool keep_ap_pll) -{ - return 0; -} - -static inline u8 db8500_prcmu_get_power_state_result(void) -{ - return 0; -} - -static inline void db8500_prcmu_enable_wakeups(u32 wakeups) {} - -static inline int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state) -{ - return 0; -} - -static inline int db8500_prcmu_request_clock(u8 clock, bool enable) -{ - return 0; -} - -static inline int db8500_prcmu_set_display_clocks(void) -{ - return 0; -} - -static inline int db8500_prcmu_disable_dsipll(void) -{ - return 0; -} - -static inline int db8500_prcmu_enable_dsipll(void) -{ - return 0; -} - -static inline int db8500_prcmu_config_esram0_deep_sleep(u8 state) -{ - return 0; -} - -static inline void db8500_prcmu_config_abb_event_readout(u32 abb_events) {} - -static inline void db8500_prcmu_get_abb_event_buffer(void __iomem **buf) {} - -static inline u16 db8500_prcmu_get_reset_code(void) -{ - return 0; -} - -static inline int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off) -{ - return 0; -} - -static inline int db8500_prcmu_enable_a9wdog(u8 id) -{ - return 0; -} - -static inline int db8500_prcmu_disable_a9wdog(u8 id) -{ - return 0; -} - -static inline int db8500_prcmu_kick_a9wdog(u8 id) -{ - return 0; -} - -static inline int db8500_prcmu_load_a9wdog(u8 id, u32 val) -{ - return 0; -} - -static inline bool db8500_prcmu_is_ac_wake_requested(void) -{ - return 0; -} - -static inline int db8500_prcmu_set_arm_opp(u8 opp) -{ - return 0; -} - -static inline int db8500_prcmu_get_arm_opp(void) -{ - return 0; -} - -static inline u32 db8500_prcmu_read(unsigned int reg) -{ - return 0; -} - -static inline void db8500_prcmu_write(unsigned int reg, u32 value) {} - -static inline void db8500_prcmu_write_masked(unsigned int reg, u32 mask, - u32 value) {} - #endif /* !CONFIG_MFD_DB8500_PRCMU */ #endif /* __MFD_DB8500_PRCMU_H */ diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index aab183d..d76114e 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -213,6 +213,23 @@ enum ddr_pwrst { DDR_PWR_STATE_OFFHIGHLAT = 0x03 }; +/** + * enum ap_pwrst_trans - Transition states defined in PRCMU firmware + * @NO_TRANSITION: No power state transition + * @APEXECUTE_TO_APSLEEP: Power state transition from ApExecute to ApSleep + * @APIDLE_TO_APSLEEP: Power state transition from ApIdle to ApSleep + * @APEXECUTE_TO_APDEEPSLEEP: Power state transition from ApExecute to + * ApDeepSleep + * @APEXECUTE_TO_APIDLE: Power state transition from ApExecute to ApIdle + */ +enum ap_pwrst_trans { + PRCMU_AP_NO_CHANGE = 0x00, + PRCMU_AP_SLEEP, + PRCMU_AP_DEEP_SLEEP, + PRCMU_AP_IDLE, + PRCMU_AP_DEEP_IDLE, +}; + struct prcmu_tcdm_map { u32 tcdm_size; u32 legacy_offset; @@ -224,77 +241,25 @@ struct prcmu_tcdm_map { #include -static inline void __init prcmu_early_init(struct prcmu_tcdm_map *map) -{ - return db8500_prcmu_early_init(map); -} - -static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk, - bool keep_ap_pll) -{ - return db8500_prcmu_set_power_state(state, keep_ulp_clk, - keep_ap_pll); -} - -static inline u8 prcmu_get_power_state_result(void) -{ - return db8500_prcmu_get_power_state_result(); -} - -static inline int prcmu_gic_decouple(void) -{ - return db8500_prcmu_gic_decouple(); -} - -static inline int prcmu_gic_recouple(void) -{ - return db8500_prcmu_gic_recouple(); -} - -static inline bool prcmu_gic_pending_irq(void) -{ - return db8500_prcmu_gic_pending_irq(); -} - -static inline bool prcmu_is_cpu_in_wfi(int cpu) -{ - return db8500_prcmu_is_cpu_in_wfi(cpu); -} - -static inline int prcmu_copy_gic_settings(void) -{ - return db8500_prcmu_copy_gic_settings(); -} - -static inline bool prcmu_pending_irq(void) -{ - return db8500_prcmu_pending_irq(); -} +void prcmu_early_init(struct prcmu_tcdm_map *map); -static inline int prcmu_set_epod(u16 epod_id, u8 epod_state) -{ - return db8500_prcmu_set_epod(epod_id, epod_state); -} +int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll); +u8 prcmu_get_power_state_result(void); -static inline void prcmu_enable_wakeups(u32 wakeups) -{ - db8500_prcmu_enable_wakeups(wakeups); -} +int prcmu_gic_decouple(void); +int prcmu_gic_recouple(void); +bool prcmu_gic_pending_irq(void); +bool prcmu_is_cpu_in_wfi(int cpu); +int prcmu_copy_gic_settings(void); +bool prcmu_pending_irq(void); -static inline void prcmu_disable_wakeups(void) -{ - prcmu_enable_wakeups(0); -} +int prcmu_set_epod(u16 epod_id, u8 epod_state); -static inline void prcmu_config_abb_event_readout(u32 abb_events) -{ - db8500_prcmu_config_abb_event_readout(abb_events); -} +void prcmu_enable_wakeups(u32 wakeups); +void prcmu_disable_wakeups(void); -static inline void prcmu_get_abb_event_buffer(void __iomem **buf) -{ - db8500_prcmu_get_abb_event_buffer(buf); -} +void prcmu_config_abb_event_readout(u32 abb_events); +void prcmu_get_abb_event_buffer(void __iomem **buf); int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); @@ -302,65 +267,35 @@ int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size); int prcmu_config_clkout(u8 clkout, u8 source, u8 div); -static inline int prcmu_request_clock(u8 clock, bool enable) -{ - return db8500_prcmu_request_clock(clock, enable); -} +int prcmu_request_clock(u8 clock, bool enable); unsigned long prcmu_clock_rate(u8 clock); long prcmu_round_clock_rate(u8 clock, unsigned long rate); int prcmu_set_clock_rate(u8 clock, unsigned long rate); -static inline int prcmu_set_ddr_opp(u8 opp) -{ - return db8500_prcmu_set_ddr_opp(opp); -} -static inline int prcmu_get_ddr_opp(void) -{ - return db8500_prcmu_get_ddr_opp(); -} +int prcmu_set_ddr_opp(u8 opp); +int prcmu_get_ddr_opp(void); -static inline int prcmu_set_arm_opp(u8 opp) -{ - return db8500_prcmu_set_arm_opp(opp); -} +int prcmu_set_arm_opp(u8 opp); -static inline int prcmu_get_arm_opp(void) -{ - return db8500_prcmu_get_arm_opp(); -} +int prcmu_get_arm_opp(void); -static inline int prcmu_set_ape_opp(u8 opp) -{ - return db8500_prcmu_set_ape_opp(opp); -} +int prcmu_set_ape_opp(u8 opp); -static inline int prcmu_get_ape_opp(void) -{ - return db8500_prcmu_get_ape_opp(); -} +int prcmu_get_ape_opp(void); -static inline void prcmu_system_reset(u16 reset_code) -{ - return db8500_prcmu_system_reset(reset_code); -} +void prcmu_system_reset(u16 reset_code); -static inline u16 prcmu_get_reset_code(void) -{ - return db8500_prcmu_get_reset_code(); -} +u16 prcmu_get_reset_code(void); int prcmu_ac_wake_req(void); void prcmu_ac_sleep_req(void); -static inline void prcmu_modem_reset(void) -{ - return db8500_prcmu_modem_reset(); -} -static inline bool prcmu_is_ac_wake_requested(void) -{ - return db8500_prcmu_is_ac_wake_requested(); -} +void prcmu_modem_reset(void); + +bool prcmu_is_ac_wake_requested(void); + +bool prcmu_has_arm_maxopp(void); static inline int prcmu_set_display_clocks(void) { @@ -377,10 +312,7 @@ static inline int prcmu_enable_dsipll(void) return db8500_prcmu_enable_dsipll(); } -static inline int prcmu_config_esram0_deep_sleep(u8 state) -{ - return db8500_prcmu_config_esram0_deep_sleep(state); -} +int prcmu_config_esram0_deep_sleep(u8 state); static inline int prcmu_config_hotdog(u8 threshold) { @@ -402,300 +334,215 @@ static inline int prcmu_stop_temp_sense(void) return db8500_prcmu_stop_temp_sense(); } -static inline u32 prcmu_read(unsigned int reg) -{ - return db8500_prcmu_read(reg); -} - -static inline void prcmu_write(unsigned int reg, u32 value) -{ - db8500_prcmu_write(reg, value); -} - -static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) -{ - db8500_prcmu_write_masked(reg, mask, value); -} - -static inline int prcmu_enable_a9wdog(u8 id) -{ - return db8500_prcmu_enable_a9wdog(id); -} - -static inline int prcmu_disable_a9wdog(u8 id) -{ - return db8500_prcmu_disable_a9wdog(id); -} - -static inline int prcmu_kick_a9wdog(u8 id) -{ - return db8500_prcmu_kick_a9wdog(id); -} - -static inline int prcmu_load_a9wdog(u8 id, u32 timeout) -{ - return db8500_prcmu_load_a9wdog(id, timeout); -} - -static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off) -{ - return db8500_prcmu_config_a9wdog(num, sleep_auto_off); -} -#else - -static inline void __init prcmu_early_init(struct prcmu_tcdm_map *map) {} - -static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk, - bool keep_ap_pll) -{ - return 0; -} - -static inline int prcmu_set_epod(u16 epod_id, u8 epod_state) -{ - return 0; -} - -static inline void prcmu_enable_wakeups(u32 wakeups) {} - -static inline void prcmu_disable_wakeups(void) {} - -static inline int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) -{ - return -ENOSYS; -} - -static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) -{ - return -ENOSYS; -} - -static inline int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, - u8 size) -{ - return -ENOSYS; -} - -static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div) -{ - return 0; -} - -static inline int prcmu_request_clock(u8 clock, bool enable) -{ - return 0; -} +u32 prcmu_read(unsigned int reg); +void prcmu_write(unsigned int reg, u32 value); +void prcmu_write_masked(unsigned int reg, u32 mask, u32 value); -static inline long prcmu_round_clock_rate(u8 clock, unsigned long rate) -{ - return 0; -} +int prcmu_enable_a9wdog(u8 id); +int prcmu_disable_a9wdog(u8 id); +int prcmu_kick_a9wdog(u8 id); +int prcmu_load_a9wdog(u8 id, u32 timeout); +int prcmu_config_a9wdog(u8 num, bool sleep_auto_off); -static inline int prcmu_set_clock_rate(u8 clock, unsigned long rate) -{ - return 0; -} -static inline unsigned long prcmu_clock_rate(u8 clock) -{ - return 0; -} +/* prcmu_get_val /prcmu_set_val */ +enum prcmu_val { + DDR_OPP, + ARM_OPP, + APE_OPP, -static inline int prcmu_set_ape_opp(u8 opp) -{ - return 0; -} + PRCMU_VAL_MAX /* used for dimensioning */ +}; -static inline int prcmu_get_ape_opp(void) -{ - return APE_100_OPP; -} +int prcmu_set_val(enum prcmu_val type, u32 value); +int prcmu_get_val(enum prcmu_val type); -static inline int prcmu_set_arm_opp(u8 opp) -{ - return 0; -} +/* prcmu_enable/prcmu_disable */ +enum prcmu_out { + SPI2_MUX, + STM_MOD_UART_MUX, + STM_APE_MUX, -static inline int prcmu_get_arm_opp(void) -{ - return ARM_100_OPP; -} + PRCMU_OUT_MAX /* used for dimensioning */ +}; -static inline int prcmu_set_ddr_opp(u8 opp) -{ - return 0; -} +int prcmu_enable(enum prcmu_out out); +int prcmu_disable(enum prcmu_out out); -static inline int prcmu_get_ddr_opp(void) -{ - return DDR_100_OPP; -} -static inline void prcmu_system_reset(u16 reset_code) {} +struct prcmu_out_data { + enum prcmu_out out; + int (*enable)(void); + int (*disable)(void); +}; -static inline u16 prcmu_get_reset_code(void) -{ - return 0; -} +struct prcmu_val_data { + enum prcmu_val val; + int (*get_val)(void); + int (*set_val)(u8 value); +}; -static inline int prcmu_ac_wake_req(void) -{ - return 0; -} -static inline void prcmu_ac_sleep_req(void) {} +/** + * @brief mfd device dbx500-prmcu early fops + */ +struct prcmu_early_data { + /* reset */ + void (*system_reset) (u16 reset_code); -static inline void prcmu_modem_reset(void) {} + /* clock api */ + int (*config_clkout) (u8 clkout, u8 source, u8 div); + int (*request_clock) (u8 clock, bool enable); -static inline bool prcmu_is_ac_wake_requested(void) -{ - return false; -} + /* direct access to prcmu reg */ + u32 (*read) (unsigned int reg); + void (*write) (unsigned int reg, u32 value); + void (*write_masked) (unsigned int reg, u32 mask, u32 value); -static inline int prcmu_set_display_clocks(void) -{ - return 0; -} -static inline int prcmu_disable_dsipll(void) -{ - return 0; -} + /* other specific 8500 */ + long (*round_clock_rate) (u8 clock, unsigned long rate); + int (*set_clock_rate) (u8 clock, unsigned long rate); + unsigned long (*clock_rate) (u8 clock); + /* clock specific */ + struct prcmu_fw_version *(*get_fw_version) (void); + bool (*has_arm_maxopp)(void); -static inline int prcmu_enable_dsipll(void) -{ - return 0; -} +}; -static inline int prcmu_config_esram0_deep_sleep(u8 state) -{ - return 0; -} +/** + * @brief mfd device dbx500-prmcu platform data + */ +struct prcmu_probe_data { + /* ux500 soc sysfs */ + u16 (*get_reset_code) (void); + + /* pm/suspend.c */ + int (*config_esram0_deep_sleep) (u8 state); + void (*enable_wakeups)(u32 wakeups); + bool (*is_ac_wake_requested) (void); + int (*set_power_state) (u8 state, bool keep_ulp_clk, + bool keep_ap_pll); + u8 (*get_power_state_result) (void); + + /* modem */ + void (*modem_reset)(void); + + /* no used at all */ + void (*config_abb_event_readout) (u32 abb_events); + void (*get_abb_event_buffer) (void __iomem **buf); + + /* abb access */ + int (*abb_read) (u8 slave, u8 reg, u8 *value, u8 size); + int (*abb_write) (u8 slave, u8 reg, u8 *value, u8 size); + + u32 (*get_reset_status)(void); + /* other u8500 specific */ + int (*request_ape_opp_100_voltage) (bool enable); + void (*configure_auto_pm) (struct prcmu_auto_pm_config *sleep, + struct prcmu_auto_pm_config *idle); + int (*set_epod) (u16 epod_id, u8 epod_state); + + /* abb specific */ + int (*abb_write_masked) (u8 slave, u8 reg, u8 *value, + u8 *mask, u8 size); + + /* watchdog */ + int (*config_a9wdog) (u8 num, bool sleep_auto_off); + int (*enable_a9wdog) (u8 id); + int (*disable_a9wdog) (u8 id); + int (*kick_a9wdog) (u8 id); + int (*load_a9wdog) (u8 id, u32 val); +}; -static inline void prcmu_config_abb_event_readout(u32 abb_events) {} +/* on u8500 default behaviour return 0 */ +struct prcmu_probe_cpuhp_data { + int (*stay_in_wfi_check)(void); + int (*replug_cpu1) (void); + int (*unplug_cpu1) (void); +}; -static inline void prcmu_get_abb_event_buffer(void __iomem **buf) -{ - *buf = NULL; -} -static inline int prcmu_config_hotdog(u8 threshold) -{ - return 0; -} +enum prcmu_fops_type { + PRCMU_VAL, + PRCMU_OUT, + PRCMU_EARLY, + PRCMU_PROBE, + PRCMU_PROBE_CPU_HP, + PRCMU_APE_AGE, +}; -static inline int prcmu_config_hotmon(u8 low, u8 high) -{ - return 0; -} +struct prcmu_fops_register { + enum prcmu_fops_type fops; + int size; + union { + struct prcmu_val_data *pval; + struct prcmu_out_data *pout; + struct prcmu_early_data *pearly; + struct prcmu_probe_data *pprobe; + struct prcmu_probe_cpuhp_data *pprobe_cpuhp; + bool (*check_ape_age)(void); + } data; +}; -static inline int prcmu_start_temp_sense(u16 cycles32k) -{ - return 0; -} +/** + * @brief mfd device dbx500-prcmu platform data + */ +struct prcmu_fops_register_data { + int size; + struct prcmu_fops_register *tab; +}; -static inline int prcmu_stop_temp_sense(void) -{ - return 0; -} +/** + * struct dbx500_regulator_init_data - mfd device prcmu-regulators data + * + */ +struct dbx500_regulator_init_data { + int (*set_epod) (u16 epod_id, u8 epod_state); + void *regulators; + int reg_num; +}; -static inline u32 prcmu_read(unsigned int reg) -{ - return 0; -} +#else -static inline void prcmu_write(unsigned int reg, u32 value) {} +static inline void __init prcmu_early_init(struct prcmu_tcdm_map *map) {} -static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {} #endif -static inline void prcmu_set(unsigned int reg, u32 bits) -{ - prcmu_write_masked(reg, bits, bits); -} - -static inline void prcmu_clear(unsigned int reg, u32 bits) -{ - prcmu_write_masked(reg, bits, 0); -} #if defined(CONFIG_UX500_SOC_DB8500) /** * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1. */ -static inline void prcmu_enable_spi2(void) -{ - if (cpu_is_u8500()) - prcmu_set(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT); -} +void prcmu_enable_spi2(void); /** * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1. */ -static inline void prcmu_disable_spi2(void) -{ - if (cpu_is_u8500()) - prcmu_clear(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT); -} - +void prcmu_disable_spi2(void); /** * prcmu_enable_stm_mod_uart - Enables pin muxing for STMMOD * and UARTMOD on OtherAlternateC3. */ -static inline void prcmu_enable_stm_mod_uart(void) -{ - if (cpu_is_u8500()) { - prcmu_set(DB8500_PRCM_GPIOCR, - (DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 | - DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0)); - } -} +void prcmu_enable_stm_mod_uart(void); /** * prcmu_disable_stm_mod_uart - Disables pin muxing for STMMOD * and UARTMOD on OtherAlternateC3. */ -static inline void prcmu_disable_stm_mod_uart(void) -{ - if (cpu_is_u8500()) { - prcmu_clear(DB8500_PRCM_GPIOCR, - (DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 | - DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0)); - } -} +void prcmu_disable_stm_mod_uart(void); /** * prcmu_enable_stm_ape - Enables pin muxing for STM APE on OtherAlternateC1. */ -static inline void prcmu_enable_stm_ape(void) -{ - if (cpu_is_u8500()) { - prcmu_set(DB8500_PRCM_GPIOCR, - DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD); - } -} +void prcmu_enable_stm_ape(void); /** * prcmu_disable_stm_ape - Disables pin muxing for STM APE on OtherAlternateC1. */ -static inline void prcmu_disable_stm_ape(void) -{ - if (cpu_is_u8500()) { - prcmu_clear(DB8500_PRCM_GPIOCR, - DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD); - } -} - -#else - -static inline void prcmu_enable_spi2(void) {} -static inline void prcmu_disable_spi2(void) {} -static inline void prcmu_enable_stm_mod_uart(void) {} -static inline void prcmu_disable_stm_mod_uart(void) {} -static inline void prcmu_enable_stm_ape(void) {} -static inline void prcmu_disable_stm_ape(void) {} +void prcmu_disable_stm_ape(void); #endif