提交 ad363e09 编写于 作者: L Linus Torvalds

Merge branch 'for-torvalds' of...

Merge branch 'for-torvalds' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson

* 'for-torvalds' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson:
  mach-ux500: voltage domain regulators for DB8500
  cpufreq: make DB8500 cpufreq driver compile
  cpufreq: update DB8500 cpufreq driver
  mach-ux500: move CPUfreq driver to cpufreq subsystem
  mfd: add DB5500 PRCMU driver
  mfd: update DB8500 PRCMU driver
  mach-ux500: move the DB8500 PRCMU driver to MFD
  mach-ux500: make PRCMU base address dynamic
  mach-ux500: rename PRCMU driver per SoC
  mach-ux500: update ASIC version detection
  mach-ux500: update SoC and board IRQ handling
  mach-ux500: update the DB5500 register file
  mach-ux500: update the DB8500 register file
......@@ -12,9 +12,12 @@ menu "Ux500 SoC"
config UX500_SOC_DB5500
bool "DB5500"
select MFD_DB5500_PRCMU
config UX500_SOC_DB8500
bool "DB8500"
select MFD_DB8500_PRCMU
select REGULATOR_DB8500_PRCMU
endmenu
......
......@@ -5,7 +5,7 @@
obj-y := clock.o cpu.o devices.o devices-common.o \
id.o usb.o
obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o
obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o
obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \
board-mop500-regulators.o \
board-mop500-uib.o board-mop500-stuib.o \
......@@ -17,4 +17,4 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o
obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
......@@ -188,6 +188,8 @@ void __init u5500_map_io(void)
ux500_map_io();
iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc));
_PRCMU_BASE = __io_address(U5500_PRCMU_BASE);
}
static int usb_db5500_rx_dma_cfg[] = {
......
......@@ -87,6 +87,8 @@ void __init u8500_map_io(void)
iotable_init(u8500_v1_io_desc, ARRAY_SIZE(u8500_v1_io_desc));
else if (cpu_is_u8500v2())
iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc));
_PRCMU_BASE = __io_address(U8500_PRCMU_BASE);
}
static struct resource db8500_pmu_resources[] = {
......@@ -129,9 +131,14 @@ static struct platform_device db8500_pmu_device = {
.dev.platform_data = &db8500_pmu_platdata,
};
static struct platform_device db8500_prcmu_device = {
.name = "db8500-prcmu",
};
static struct platform_device *platform_devs[] __initdata = {
&u8500_dma40_device,
&db8500_pmu_device,
&db8500_prcmu_device,
};
static resource_size_t __initdata db8500_gpio_base[] = {
......
......@@ -8,6 +8,8 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/mfd/db8500-prcmu.h>
#include <linux/mfd/db5500-prcmu.h>
#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
......@@ -19,10 +21,11 @@
#include <mach/hardware.h>
#include <mach/setup.h>
#include <mach/devices.h>
#include <mach/prcmu.h>
#include "clock.h"
void __iomem *_PRCMU_BASE;
#ifdef CONFIG_CACHE_L2X0
static void __iomem *l2x0_base;
#endif
......@@ -47,6 +50,8 @@ void __init ux500_init_irq(void)
* Init clocks here so that they are available for system timer
* initialization.
*/
if (cpu_is_u5500())
db5500_prcmu_early_init();
if (cpu_is_u8500())
prcmu_early_init();
clk_init();
......
......@@ -17,6 +17,8 @@
#define U5500_GIC_DIST_BASE 0xA0411000
#define U5500_GIC_CPU_BASE 0xA0410100
#define U5500_DMA_BASE 0x90030000
#define U5500_STM_BASE 0x90020000
#define U5500_STM_REG_BASE (U5500_STM_BASE + 0xF000)
#define U5500_MCDE_BASE 0xA0400000
#define U5500_MODEM_BASE 0xB0000000
#define U5500_L2CC_BASE 0xA0412000
......@@ -29,7 +31,9 @@
#define U5500_NAND0_BASE 0x60000000
#define U5500_NAND1_BASE 0x70000000
#define U5500_TWD_BASE 0xa0410600
#define U5500_ICN_BASE 0xA0040000
#define U5500_B2R2_BASE 0xa0200000
#define U5500_BOOT_ROM_BASE 0x90000000
#define U5500_FSMC_BASE (U5500_PER1_BASE + 0x0000)
#define U5500_SDI0_BASE (U5500_PER1_BASE + 0x1000)
......@@ -60,6 +64,7 @@
#define U5500_MSP1_BASE (U5500_PER4_BASE + 0x9000)
#define U5500_GPIO2_BASE (U5500_PER4_BASE + 0xA000)
#define U5500_CDETECT_BASE (U5500_PER4_BASE + 0xF000)
#define U5500_PRCMU_TCDM_BASE (U5500_PER4_BASE + 0x18000)
#define U5500_SPI0_BASE (U5500_PER5_BASE + 0x0000)
#define U5500_SPI1_BASE (U5500_PER5_BASE + 0x1000)
......@@ -83,7 +88,7 @@
#define U5500_HASH0_BASE (U5500_PER6_BASE + 0x1000)
#define U5500_HASH1_BASE (U5500_PER6_BASE + 0x2000)
#define U5500_PKA_BASE (U5500_PER6_BASE + 0x4000)
#define U5500_PKAM_BASE (U5500_PER6_BASE + 0x5000)
#define U5500_PKAM_BASE (U5500_PER6_BASE + 0x5100)
#define U5500_MTU0_BASE (U5500_PER6_BASE + 0x6000)
#define U5500_MTU1_BASE (U5500_PER6_BASE + 0x7000)
#define U5500_CR_BASE (U5500_PER6_BASE + 0x8000)
......@@ -114,8 +119,19 @@
#define U5500_MBOX2_LOCAL_START (U5500_MBOX_BASE + 0x20)
#define U5500_MBOX2_LOCAL_END (U5500_MBOX_BASE + 0x3F)
#define U5500_ESRAM_BASE 0x40000000
#define U5500_ACCCON_BASE_SEC (0xBFFF0000)
#define U5500_ACCCON_BASE (0xBFFF1000)
#define U5500_ACCCON_CPUVEC_RESET_ADDR_OFFSET (0x00000020)
#define U5500_ACCCON_ACC_CPU_CTRL_OFFSET (0x000000BC)
#define U5500_ESRAM_BASE 0x40000000
#define U5500_ESRAM_DMA_LCPA_OFFSET 0x10000
#define U5500_DMA_LCPA_BASE (U5500_ESRAM_BASE + U5500_ESRAM_DMA_LCPA_OFFSET)
#define U5500_MCDE_SIZE 0x1000
#define U5500_DSI_LINK_SIZE 0x1000
#define U5500_DSI_LINK_COUNT 0x2
#define U5500_DSI_LINK1_BASE (U5500_MCDE_BASE + U5500_MCDE_SIZE)
#define U5500_DSI_LINK2_BASE (U5500_DSI_LINK1_BASE + U5500_DSI_LINK_SIZE)
#endif
......@@ -15,8 +15,13 @@
#define U8500_ESRAM_BANK2 (U8500_ESRAM_BANK1 + U8500_ESRAM_BANK_SIZE)
#define U8500_ESRAM_BANK3 (U8500_ESRAM_BANK2 + U8500_ESRAM_BANK_SIZE)
#define U8500_ESRAM_BANK4 (U8500_ESRAM_BANK3 + U8500_ESRAM_BANK_SIZE)
/* Use bank 4 for DMA LCPA */
#define U8500_DMA_LCPA_BASE U8500_ESRAM_BANK4
/*
* on V1 DMA uses 4KB for logical parameters position is right after the 64KB
* reserved for security
*/
#define U8500_ESRAM_DMA_LCPA_OFFSET 0x10000
#define U8500_DMA_LCPA_BASE (U8500_ESRAM_BANK0 + U8500_ESRAM_DMA_LCPA_OFFSET)
#define U8500_DMA_LCPA_BASE_ED (U8500_ESRAM_BANK4 + 0x4000)
#define U8500_PER3_BASE 0x80000000
......@@ -27,9 +32,12 @@
#define U8500_B2R2_BASE 0x80130000
#define U8500_HSEM_BASE 0x80140000
#define U8500_PER4_BASE 0x80150000
#define U8500_TPIU_BASE 0x80190000
#define U8500_ICN_BASE 0x81000000
#define U8500_BOOT_ROM_BASE 0x90000000
/* ASIC ID is at 0xbf4 offset within this region */
#define U8500_ASIC_ID_BASE 0x9001D000
#define U8500_PER6_BASE 0xa03c0000
#define U8500_PER5_BASE 0xa03e0000
......@@ -70,13 +78,15 @@
/* per6 base addresses */
#define U8500_RNG_BASE (U8500_PER6_BASE + 0x0000)
#define U8500_PKA_BASE (U8500_PER6_BASE + 0x1000)
#define U8500_PKAM_BASE (U8500_PER6_BASE + 0x2000)
#define U8500_HASH0_BASE (U8500_PER6_BASE + 0x1000)
#define U8500_HASH1_BASE (U8500_PER6_BASE + 0x2000)
#define U8500_PKA_BASE (U8500_PER6_BASE + 0x4000)
#define U8500_PKAM_BASE (U8500_PER6_BASE + 0x5100)
#define U8500_MTU0_BASE (U8500_PER6_BASE + 0x6000) /* v1 */
#define U8500_MTU1_BASE (U8500_PER6_BASE + 0x7000) /* v1 */
#define U8500_CR_BASE (U8500_PER6_BASE + 0x8000) /* v1 */
#define U8500_CRYPTO0_BASE (U8500_PER6_BASE + 0xa000)
#define U8500_CRYPTO1_BASE (U8500_PER6_BASE + 0xb000)
#define U8500_CRYP0_BASE (U8500_PER6_BASE + 0xa000)
#define U8500_CRYP1_BASE (U8500_PER6_BASE + 0xb000)
#define U8500_CLKRST6_BASE (U8500_PER6_BASE + 0xf000)
/* per5 base addresses */
......@@ -93,7 +103,8 @@
#define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000)
#define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000)
#define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000)
#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000)
#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000)
#define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000)
/* per3 base addresses */
#define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000)
......@@ -124,6 +135,7 @@
#define U8500_I2C1_BASE (U8500_PER1_BASE + 0x2000)
#define U8500_MSP0_BASE (U8500_PER1_BASE + 0x3000)
#define U8500_MSP1_BASE (U8500_PER1_BASE + 0x4000)
#define U8500_MSP3_BASE (U8500_PER1_BASE + 0x5000)
#define U8500_SDI0_BASE (U8500_PER1_BASE + 0x6000)
#define U8500_I2C2_BASE (U8500_PER1_BASE + 0x8000)
#define U8500_SPI3_BASE (U8500_PER1_BASE + 0x9000)
......@@ -143,4 +155,15 @@
#define U8500_GPIOBANK7_BASE (U8500_GPIO2_BASE + 0x80)
#define U8500_GPIOBANK8_BASE U8500_GPIO3_BASE
#define U8500_MCDE_SIZE 0x1000
#define U8500_DSI_LINK_SIZE 0x1000
#define U8500_DSI_LINK1_BASE (U8500_MCDE_BASE + U8500_MCDE_SIZE)
#define U8500_DSI_LINK2_BASE (U8500_DSI_LINK1_BASE + U8500_DSI_LINK_SIZE)
#define U8500_DSI_LINK3_BASE (U8500_DSI_LINK2_BASE + U8500_DSI_LINK_SIZE)
#define U8500_DSI_LINK_COUNT 0x3
/* Modem and APE physical addresses */
#define U8500_MODEM_BASE 0xe000000
#define U8500_APE_BASE 0x6000000
#endif
......@@ -35,6 +35,7 @@
#ifndef __ASSEMBLY__
#include <mach/id.h>
extern void __iomem *_PRCMU_BASE;
#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
......
......@@ -75,6 +75,26 @@ static inline bool __attribute_const__ cpu_is_u8500v2(void)
return cpu_is_u8500() && ((dbx500_revision() & 0xf0) == 0xB0);
}
static inline bool cpu_is_u8500v20(void)
{
return cpu_is_u8500() && (dbx500_revision() == 0xB0);
}
static inline bool cpu_is_u8500v21(void)
{
return cpu_is_u8500() && (dbx500_revision() == 0xB1);
}
static inline bool cpu_is_u8500v20_or_later(void)
{
return cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11();
}
static inline bool ux500_is_svp(void)
{
return false;
}
#define ux500_unknown_soc() BUG()
#endif
......@@ -50,6 +50,11 @@
#define MOP500_IRQ_END MOP500_NR_IRQS
/*
* We may have several boards, but only one will run at a
* time, so the one with most IRQs will bump this ahead,
* but the IRQ_BOARD_START remains the same for either board.
*/
#if MOP500_IRQ_END > IRQ_BOARD_END
#undef IRQ_BOARD_END
#define IRQ_BOARD_END MOP500_IRQ_END
......
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef __MACH_IRQS_BOARD_U5500_H
#define __MACH_IRQS_BOARD_U5500_H
#define AB5500_NR_IRQS 5
#define IRQ_AB5500_BASE IRQ_BOARD_START
#define IRQ_AB5500_END (IRQ_AB5500_BASE + AB5500_NR_IRQS)
#define U5500_IRQ_END IRQ_AB5500_END
#if IRQ_BOARD_END < U5500_IRQ_END
#undef IRQ_BOARD_END
#define IRQ_BOARD_END U5500_IRQ_END
#endif
#endif
......@@ -83,4 +83,31 @@
#define IRQ_DB5500_GPIO6 (IRQ_SHPI_START + 125)
#define IRQ_DB5500_GPIO7 (IRQ_SHPI_START + 126)
#ifdef CONFIG_UX500_SOC_DB5500
/*
* After the GPIO ones we reserve a range of IRQ:s in which virtual
* IRQ:s representing modem IRQ:s can be allocated
*/
#define IRQ_MODEM_EVENTS_BASE IRQ_SOC_START
#define IRQ_MODEM_EVENTS_NBR 72
#define IRQ_MODEM_EVENTS_END (IRQ_MODEM_EVENTS_BASE + IRQ_MODEM_EVENTS_NBR)
/* List of virtual IRQ:s that are allocated from the range above */
#define MBOX_PAIR0_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 43)
#define MBOX_PAIR1_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 45)
#define MBOX_PAIR2_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 41)
/*
* We may have several SoCs, but only one will run at a
* time, so the one with most IRQs will bump this ahead,
* but the IRQ_SOC_START remains the same for either SoC.
*/
#if IRQ_SOC_END < IRQ_MODEM_EVENTS_END
#undef IRQ_SOC_END
#define IRQ_SOC_END IRQ_MODEM_EVENTS_END
#endif
#endif /* CONFIG_UX500_SOC_DB5500 */
#endif
......@@ -93,4 +93,58 @@
#define IRQ_DB8500_GPIO7 (IRQ_SHPI_START + 126)
#define IRQ_DB8500_GPIO8 (IRQ_SHPI_START + 127)
#define IRQ_CA_WAKE_REQ_ED (IRQ_SHPI_START + 71)
#define IRQ_AC_READ_NOTIFICATION_0_ED (IRQ_SHPI_START + 66)
#define IRQ_AC_READ_NOTIFICATION_1_ED (IRQ_SHPI_START + 64)
#define IRQ_CA_MSG_PEND_NOTIFICATION_0_ED (IRQ_SHPI_START + 67)
#define IRQ_CA_MSG_PEND_NOTIFICATION_1_ED (IRQ_SHPI_START + 65)
#define IRQ_CA_WAKE_REQ_V1 (IRQ_SHPI_START + 83)
#define IRQ_AC_READ_NOTIFICATION_0_V1 (IRQ_SHPI_START + 78)
#define IRQ_AC_READ_NOTIFICATION_1_V1 (IRQ_SHPI_START + 76)
#define IRQ_CA_MSG_PEND_NOTIFICATION_0_V1 (IRQ_SHPI_START + 79)
#define IRQ_CA_MSG_PEND_NOTIFICATION_1_V1 (IRQ_SHPI_START + 77)
#ifdef CONFIG_UX500_SOC_DB8500
/* Virtual interrupts corresponding to the PRCMU wakeups. */
#define IRQ_PRCMU_BASE IRQ_SOC_START
#define NUM_PRCMU_WAKEUPS (IRQ_PRCMU_END - IRQ_PRCMU_BASE)
#define IRQ_PRCMU_RTC (IRQ_PRCMU_BASE)
#define IRQ_PRCMU_RTT0 (IRQ_PRCMU_BASE + 1)
#define IRQ_PRCMU_RTT1 (IRQ_PRCMU_BASE + 2)
#define IRQ_PRCMU_HSI0 (IRQ_PRCMU_BASE + 3)
#define IRQ_PRCMU_HSI1 (IRQ_PRCMU_BASE + 4)
#define IRQ_PRCMU_CA_WAKE (IRQ_PRCMU_BASE + 5)
#define IRQ_PRCMU_USB (IRQ_PRCMU_BASE + 6)
#define IRQ_PRCMU_ABB (IRQ_PRCMU_BASE + 7)
#define IRQ_PRCMU_ABB_FIFO (IRQ_PRCMU_BASE + 8)
#define IRQ_PRCMU_ARM (IRQ_PRCMU_BASE + 9)
#define IRQ_PRCMU_MODEM_SW_RESET_REQ (IRQ_PRCMU_BASE + 10)
#define IRQ_PRCMU_GPIO0 (IRQ_PRCMU_BASE + 11)
#define IRQ_PRCMU_GPIO1 (IRQ_PRCMU_BASE + 12)
#define IRQ_PRCMU_GPIO2 (IRQ_PRCMU_BASE + 13)
#define IRQ_PRCMU_GPIO3 (IRQ_PRCMU_BASE + 14)
#define IRQ_PRCMU_GPIO4 (IRQ_PRCMU_BASE + 15)
#define IRQ_PRCMU_GPIO5 (IRQ_PRCMU_BASE + 16)
#define IRQ_PRCMU_GPIO6 (IRQ_PRCMU_BASE + 17)
#define IRQ_PRCMU_GPIO7 (IRQ_PRCMU_BASE + 18)
#define IRQ_PRCMU_GPIO8 (IRQ_PRCMU_BASE + 19)
#define IRQ_PRCMU_CA_SLEEP (IRQ_PRCMU_BASE + 20)
#define IRQ_PRCMU_HOTMON_LOW (IRQ_PRCMU_BASE + 21)
#define IRQ_PRCMU_HOTMON_HIGH (IRQ_PRCMU_BASE + 22)
#define IRQ_PRCMU_END (IRQ_PRCMU_BASE + 23)
/*
* We may have several SoCs, but only one will run at a
* time, so the one with most IRQs will bump this ahead,
* but the IRQ_SOC_START remains the same for either SoC.
*/
#if IRQ_SOC_END < IRQ_PRCMU_END
#undef IRQ_SOC_END
#define IRQ_SOC_END IRQ_PRCMU_END
#endif
#endif /* CONFIG_UX500_SOC_DB8500 */
#endif
......@@ -10,49 +10,47 @@
#ifndef ASM_ARCH_IRQS_H
#define ASM_ARCH_IRQS_H
#include <mach/irqs-db5500.h>
#include <mach/irqs-db8500.h>
#include <mach/hardware.h>
#define IRQ_LOCALTIMER 29
#define IRQ_LOCALWDOG 30
#define IRQ_LOCALTIMER 29
#define IRQ_LOCALWDOG 30
/* Shared Peripheral Interrupt (SHPI) */
#define IRQ_SHPI_START 32
/* Interrupt numbers generic for shared peripheral */
/*
* MTU0 preserved for now until plat-nomadik is taught not to use it. Don't
* add any other IRQs here, use the irqs-dbx500.h files.
*/
#define IRQ_MTU0 (IRQ_SHPI_START + 4)
/* There are 128 shared peripheral interrupts assigned to
* INTID[160:32]. The first 32 interrupts are reserved.
*/
#define DBX500_NR_INTERNAL_IRQS 161
#define DBX500_NR_INTERNAL_IRQS 160
/* After chip-specific IRQ numbers we have the GPIO ones */
#define NOMADIK_NR_GPIO 288
#define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + DBX500_NR_INTERNAL_IRQS)
#define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - DBX500_NR_INTERNAL_IRQS)
#define IRQ_BOARD_START NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO)
#define IRQ_GPIO_END NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO)
#define IRQ_SOC_START IRQ_GPIO_END
/* This will be overridden by SoC-specific irq headers */
#define IRQ_SOC_END IRQ_SOC_START
#include <mach/irqs-db5500.h>
#include <mach/irqs-db8500.h>
#define IRQ_BOARD_START IRQ_SOC_END
/* This will be overridden by board-specific irq headers */
#define IRQ_BOARD_END IRQ_BOARD_START
#define IRQ_BOARD_END IRQ_BOARD_START
#ifdef CONFIG_MACH_U8500
#include <mach/irqs-board-mop500.h>
#endif
/*
* After the board specific IRQ:s we reserve a range of IRQ:s in which virtual
* IRQ:s representing modem IRQ:s can be allocated
*/
#define IRQ_MODEM_EVENTS_BASE (IRQ_BOARD_END + 1)
#define IRQ_MODEM_EVENTS_NBR 72
#define IRQ_MODEM_EVENTS_END (IRQ_MODEM_EVENTS_BASE + IRQ_MODEM_EVENTS_NBR)
/* List of virtual IRQ:s that are allocated from the range above */
#define MBOX_PAIR0_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 43)
#define MBOX_PAIR1_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 45)
#define MBOX_PAIR2_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 41)
#ifdef CONFIG_MACH_U5500
#include <mach/irqs-board-u5500.h>
#endif
#define NR_IRQS IRQ_MODEM_EVENTS_END
#define NR_IRQS IRQ_BOARD_END
#endif /* ASM_ARCH_IRQS_H */
/*
* Copyright (C) STMicroelectronics 2009
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Sundar Iyer <sundar.iyer@stericsson.com>
* Author: Martin Persson <martin.persson@stericsson.com>
*
* License Terms: GNU General Public License v2
*
* PRCM Unit definitions
*/
#ifndef __MACH_PRCMU_DEFS_H
#define __MACH_PRCMU_DEFS_H
enum prcmu_cpu_opp {
CPU_OPP_INIT = 0x00,
CPU_OPP_NO_CHANGE = 0x01,
CPU_OPP_100 = 0x02,
CPU_OPP_50 = 0x03,
CPU_OPP_MAX = 0x04,
CPU_OPP_EXT_CLK = 0x07
};
enum prcmu_ape_opp {
APE_OPP_NO_CHANGE = 0x00,
APE_OPP_100 = 0x02,
APE_OPP_50 = 0x03,
};
#endif /* __MACH_PRCMU_DEFS_H */
/*
* Copyright (C) STMicroelectronics 2009
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
* Author: Sundar Iyer <sundar.iyer@stericsson.com>
* Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
*
* License Terms: GNU General Public License v2
*
* PRCM Unit f/w API
*/
#ifndef __MACH_PRCMU_H
#define __MACH_PRCMU_H
#include <mach/prcmu-defs.h>
void __init prcmu_early_init(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_set_ape_opp(enum prcmu_ape_opp opp);
int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp);
int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp,
enum prcmu_cpu_opp cpu_opp);
int prcmu_get_ape_opp(void);
int prcmu_get_cpu_opp(void);
bool prcmu_has_arm_maxopp(void);
#endif /* __MACH_PRCMU_H */
/*
* Copyright (C) STMicroelectronics 2009
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
* Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
* Author: Sundar Iyer <sundar.iyer@stericsson.com>
* Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
*
* U8500 PRCM Unit interface driver
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/mutex.h>
#include <linux/completion.h>
#include <linux/jiffies.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <mach/hardware.h>
#include <mach/prcmu-regs.h>
#include <mach/prcmu-defs.h>
/* Global var to runtime determine TCDM base for v2 or v1 */
static __iomem void *tcdm_base;
#define _MBOX_HEADER (tcdm_base + 0xFE8)
#define MBOX_HEADER_REQ_MB0 (_MBOX_HEADER + 0x0)
#define REQ_MB1 (tcdm_base + 0xFD0)
#define REQ_MB5 (tcdm_base + 0xE44)
#define REQ_MB1_ARMOPP (REQ_MB1 + 0x0)
#define REQ_MB1_APEOPP (REQ_MB1 + 0x1)
#define REQ_MB1_BOOSTOPP (REQ_MB1 + 0x2)
#define ACK_MB1 (tcdm_base + 0xE04)
#define ACK_MB5 (tcdm_base + 0xDF4)
#define ACK_MB1_CURR_ARMOPP (ACK_MB1 + 0x0)
#define ACK_MB1_CURR_APEOPP (ACK_MB1 + 0x1)
#define REQ_MB5_I2C_SLAVE_OP (REQ_MB5)
#define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1)
#define REQ_MB5_I2C_REG (REQ_MB5 + 2)
#define REQ_MB5_I2C_VAL (REQ_MB5 + 3)
#define ACK_MB5_I2C_STATUS (ACK_MB5 + 1)
#define ACK_MB5_I2C_VAL (ACK_MB5 + 3)
#define PRCM_AVS_VARM_MAX_OPP (tcdm_base + 0x2E4)
#define PRCM_AVS_ISMODEENABLE 7
#define PRCM_AVS_ISMODEENABLE_MASK (1 << PRCM_AVS_ISMODEENABLE)
#define I2C_WRITE(slave) \
(((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0))
#define I2C_READ(slave) \
(((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0) | BIT(0))
#define I2C_STOP_EN BIT(3)
enum mb1_h {
MB1H_ARM_OPP = 1,
MB1H_APE_OPP,
MB1H_ARM_APE_OPP,
};
static struct {
struct mutex lock;
struct completion work;
struct {
u8 arm_opp;
u8 ape_opp;
u8 arm_status;
u8 ape_status;
} ack;
} mb1_transfer;
enum ack_mb5_status {
I2C_WR_OK = 0x01,
I2C_RD_OK = 0x02,
};
#define MBOX_BIT BIT
#define NUM_MBOX 8
static struct {
struct mutex lock;
struct completion work;
bool failed;
struct {
u8 status;
u8 value;
} ack;
} mb5_transfer;
/**
* 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).
* @size: The number of registers to read.
*
* 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)
{
int r;
if (size != 1)
return -EINVAL;
r = mutex_lock_interruptible(&mb5_transfer.lock);
if (r)
return r;
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
cpu_relax();
writeb(I2C_READ(slave), REQ_MB5_I2C_SLAVE_OP);
writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
writeb(reg, REQ_MB5_I2C_REG);
writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
if (!wait_for_completion_timeout(&mb5_transfer.work,
msecs_to_jiffies(500))) {
pr_err("prcmu: prcmu_abb_read timed out.\n");
r = -EIO;
goto unlock_and_return;
}
r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO);
if (!r)
*value = mb5_transfer.ack.value;
unlock_and_return:
mutex_unlock(&mb5_transfer.lock);
return r;
}
EXPORT_SYMBOL(prcmu_abb_read);
/**
* 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.
* @size: The number of registers to write.
*
* Reads register value(s) from the ABB.
* @size has to be 1 for the current firmware version.
*/
int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
{
int r;
if (size != 1)
return -EINVAL;
r = mutex_lock_interruptible(&mb5_transfer.lock);
if (r)
return r;
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
cpu_relax();
writeb(I2C_WRITE(slave), REQ_MB5_I2C_SLAVE_OP);
writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
writeb(reg, REQ_MB5_I2C_REG);
writeb(*value, REQ_MB5_I2C_VAL);
writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
if (!wait_for_completion_timeout(&mb5_transfer.work,
msecs_to_jiffies(500))) {
pr_err("prcmu: prcmu_abb_write timed out.\n");
r = -EIO;
goto unlock_and_return;
}
r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO);
unlock_and_return:
mutex_unlock(&mb5_transfer.lock);
return r;
}
EXPORT_SYMBOL(prcmu_abb_write);
static int set_ape_cpu_opps(u8 header, enum prcmu_ape_opp ape_opp,
enum prcmu_cpu_opp cpu_opp)
{
bool do_ape;
bool do_arm;
int err = 0;
do_ape = ((header == MB1H_APE_OPP) || (header == MB1H_ARM_APE_OPP));
do_arm = ((header == MB1H_ARM_OPP) || (header == MB1H_ARM_APE_OPP));
mutex_lock(&mb1_transfer.lock);
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
cpu_relax();
writeb(0, MBOX_HEADER_REQ_MB0);
writeb(cpu_opp, REQ_MB1_ARMOPP);
writeb(ape_opp, REQ_MB1_APEOPP);
writeb(0, REQ_MB1_BOOSTOPP);
writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
wait_for_completion(&mb1_transfer.work);
if ((do_ape) && (mb1_transfer.ack.ape_status != 0))
err = -EIO;
if ((do_arm) && (mb1_transfer.ack.arm_status != 0))
err = -EIO;
mutex_unlock(&mb1_transfer.lock);
return err;
}
/**
* prcmu_set_ape_opp() - Set the OPP of the APE.
* @opp: The OPP to set.
*
* This function sets the OPP of the APE.
*/
int prcmu_set_ape_opp(enum prcmu_ape_opp opp)
{
return set_ape_cpu_opps(MB1H_APE_OPP, opp, APE_OPP_NO_CHANGE);
}
EXPORT_SYMBOL(prcmu_set_ape_opp);
/**
* prcmu_set_cpu_opp() - Set the OPP of the CPU.
* @opp: The OPP to set.
*
* This function sets the OPP of the CPU.
*/
int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp)
{
return set_ape_cpu_opps(MB1H_ARM_OPP, CPU_OPP_NO_CHANGE, opp);
}
EXPORT_SYMBOL(prcmu_set_cpu_opp);
/**
* prcmu_set_ape_cpu_opps() - Set the OPPs of the APE and the CPU.
* @ape_opp: The APE OPP to set.
* @cpu_opp: The CPU OPP to set.
*
* This function sets the OPPs of the APE and the CPU.
*/
int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp,
enum prcmu_cpu_opp cpu_opp)
{
return set_ape_cpu_opps(MB1H_ARM_APE_OPP, ape_opp, cpu_opp);
}
EXPORT_SYMBOL(prcmu_set_ape_cpu_opps);
/**
* prcmu_get_ape_opp() - Get the OPP of the APE.
*
* This function gets the OPP of the APE.
*/
enum prcmu_ape_opp prcmu_get_ape_opp(void)
{
return readb(ACK_MB1_CURR_APEOPP);
}
EXPORT_SYMBOL(prcmu_get_ape_opp);
/**
* prcmu_get_cpu_opp() - Get the OPP of the CPU.
*
* This function gets the OPP of the CPU. The OPP is specified in %%.
* PRCMU_OPP_EXT is a special OPP value, not specified in %%.
*/
int prcmu_get_cpu_opp(void)
{
return readb(ACK_MB1_CURR_ARMOPP);
}
EXPORT_SYMBOL(prcmu_get_cpu_opp);
bool prcmu_has_arm_maxopp(void)
{
return (readb(PRCM_AVS_VARM_MAX_OPP) & PRCM_AVS_ISMODEENABLE_MASK)
== PRCM_AVS_ISMODEENABLE_MASK;
}
static void read_mailbox_0(void)
{
writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
}
static void read_mailbox_1(void)
{
mb1_transfer.ack.arm_opp = readb(ACK_MB1_CURR_ARMOPP);
mb1_transfer.ack.ape_opp = readb(ACK_MB1_CURR_APEOPP);
complete(&mb1_transfer.work);
writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
}
static void read_mailbox_2(void)
{
writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR);
}
static void read_mailbox_3(void)
{
writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR);
}
static void read_mailbox_4(void)
{
writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR);
}
static void read_mailbox_5(void)
{
mb5_transfer.ack.status = readb(ACK_MB5_I2C_STATUS);
mb5_transfer.ack.value = readb(ACK_MB5_I2C_VAL);
complete(&mb5_transfer.work);
writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR);
}
static void read_mailbox_6(void)
{
writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR);
}
static void read_mailbox_7(void)
{
writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR);
}
static void (* const read_mailbox[NUM_MBOX])(void) = {
read_mailbox_0,
read_mailbox_1,
read_mailbox_2,
read_mailbox_3,
read_mailbox_4,
read_mailbox_5,
read_mailbox_6,
read_mailbox_7
};
static irqreturn_t prcmu_irq_handler(int irq, void *data)
{
u32 bits;
u8 n;
bits = (readl(PRCM_ARM_IT1_VAL) & (MBOX_BIT(NUM_MBOX) - 1));
if (unlikely(!bits))
return IRQ_NONE;
for (n = 0; bits; n++) {
if (bits & MBOX_BIT(n)) {
bits -= MBOX_BIT(n);
read_mailbox[n]();
}
}
return IRQ_HANDLED;
}
void __init prcmu_early_init(void)
{
if (cpu_is_u8500v11() || cpu_is_u8500ed()) {
tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE_V1);
} else if (cpu_is_u8500v2()) {
tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
} else {
pr_err("prcmu: Unsupported chip version\n");
BUG();
}
}
static int __init prcmu_init(void)
{
if (cpu_is_u8500ed()) {
pr_err("prcmu: Unsupported chip version\n");
return 0;
}
mutex_init(&mb1_transfer.lock);
init_completion(&mb1_transfer.work);
mutex_init(&mb5_transfer.lock);
init_completion(&mb5_transfer.work);
/* Clean up the mailbox interrupts after pre-kernel code. */
writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR);
return request_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, 0,
"prcmu", NULL);
}
arch_initcall(prcmu_init);
......@@ -39,3 +39,5 @@ obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o
##################################################################################d
# ARM SoC drivers
obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
/*
* CPU frequency scaling for u8500
* Inspired by linux/arch/arm/mach-davinci/cpufreq.c
*
* Copyright (C) STMicroelectronics 2009
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
*
* Author: Sundar Iyer <sundar.iyer@stericsson.com>
* Author: Martin Persson <martin.persson@stericsson.com>
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
*
*/
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <mach/hardware.h>
#include <mach/prcmu.h>
#include <mach/prcmu-defs.h>
#define DRIVER_NAME "cpufreq-u8500"
#define CPUFREQ_NAME "u8500"
static struct device *dev;
#include <linux/slab.h>
#include <linux/mfd/db8500-prcmu.h>
#include <mach/id.h>
static struct cpufreq_frequency_table freq_table[] = {
[0] = {
.index = 0,
.frequency = 200000,
.frequency = 300000,
},
[1] = {
.index = 1,
.frequency = 300000,
.frequency = 600000,
},
[2] = {
/* Used for MAX_OPP, if available */
.index = 2,
.frequency = 600000,
.frequency = CPUFREQ_TABLE_END,
},
[3] = {
/* Used for CPU_OPP_MAX, if available */
.index = 3,
.frequency = CPUFREQ_TABLE_END,
},
[4] = {
.index = 4,
.frequency = CPUFREQ_TABLE_END,
},
};
static enum prcmu_cpu_opp index2opp[] = {
CPU_OPP_EXT_CLK,
CPU_OPP_50,
CPU_OPP_100,
CPU_OPP_MAX
static enum arm_opp idx2opp[] = {
ARM_50_OPP,
ARM_100_OPP,
ARM_MAX_OPP
};
static struct freq_attr *db8500_cpufreq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
};
static int u8500_cpufreq_verify_speed(struct cpufreq_policy *policy)
static int db8500_cpufreq_verify_speed(struct cpufreq_policy *policy)
{
return cpufreq_frequency_table_verify(policy, freq_table);
}
static int u8500_cpufreq_target(struct cpufreq_policy *policy,
static int db8500_cpufreq_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
struct cpufreq_freqs freqs;
unsigned int index;
int ret = 0;
unsigned int idx;
/*
* Ensure desired rate is within allowed range. Some govenors
* (ondemand) will just pass target_freq=0 to get the minimum.
*/
/* scale the target frequency to one of the extremes supported */
if (target_freq < policy->cpuinfo.min_freq)
target_freq = policy->cpuinfo.min_freq;
if (target_freq > policy->cpuinfo.max_freq)
target_freq = policy->cpuinfo.max_freq;
ret = cpufreq_frequency_table_target(policy, freq_table,
target_freq, relation, &index);
if (ret < 0) {
dev_err(dev, "Could not look up next frequency\n");
return ret;
/* Lookup the next frequency */
if (cpufreq_frequency_table_target
(policy, freq_table, target_freq, relation, &idx)) {
return -EINVAL;
}
freqs.old = policy->cur;
freqs.new = freq_table[index].frequency;
freqs.new = freq_table[idx].frequency;
freqs.cpu = policy->cpu;
if (freqs.old == freqs.new) {
dev_dbg(dev, "Current and target frequencies are equal\n");
if (freqs.old == freqs.new)
return 0;
}
dev_dbg(dev, "transition: %u --> %u\n", freqs.old, freqs.new);
/* pre-change notification */
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
ret = prcmu_set_cpu_opp(index2opp[index]);
if (ret < 0) {
dev_err(dev, "Failed to set OPP level\n");
return ret;
/* request the PRCM unit for opp change */
if (prcmu_set_arm_opp(idx2opp[idx])) {
pr_err("db8500-cpufreq: Failed to set OPP level\n");
return -EINVAL;
}
/* post change notification */
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
return ret;
return 0;
}
static unsigned int u8500_cpufreq_getspeed(unsigned int cpu)
static unsigned int db8500_cpufreq_getspeed(unsigned int cpu)
{
int i;
for (i = 0; prcmu_get_cpu_opp() != index2opp[i]; i++)
/* request the prcm to get the current ARM opp */
for (i = 0; prcmu_get_arm_opp() != idx2opp[i]; i++)
;
return freq_table[i].frequency;
}
static int __cpuinit u8500_cpu_init(struct cpufreq_policy *policy)
static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
{
int res;
int i;
BUILD_BUG_ON(ARRAY_SIZE(index2opp) + 1 != ARRAY_SIZE(freq_table));
BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
if (cpu_is_u8500v2()) {
freq_table[1].frequency = 400000;
freq_table[2].frequency = 800000;
if (cpu_is_u8500v2() && !prcmu_is_u8400()) {
freq_table[0].frequency = 400000;
freq_table[1].frequency = 800000;
if (prcmu_has_arm_maxopp())
freq_table[3].frequency = 1000000;
freq_table[2].frequency = 1000000;
}
/* get policy fields based on the table */
......@@ -137,13 +120,17 @@ static int __cpuinit u8500_cpu_init(struct cpufreq_policy *policy)
if (!res)
cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
else {
dev_err(dev, "u8500-cpufreq : Failed to read policy table\n");
pr_err("db8500-cpufreq : Failed to read policy table\n");
return res;
}
policy->min = policy->cpuinfo.min_freq;
policy->max = policy->cpuinfo.max_freq;
policy->cur = u8500_cpufreq_getspeed(policy->cpu);
policy->cur = db8500_cpufreq_getspeed(policy->cpu);
for (i = 0; freq_table[i].frequency != policy->cur; i++)
;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
/*
......@@ -151,61 +138,32 @@ static int __cpuinit u8500_cpu_init(struct cpufreq_policy *policy)
* function with no/some/all drivers in the notification
* list.
*/
policy->cpuinfo.transition_latency = 200 * 1000; /* in ns */
policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */
/* policy sharing between dual CPUs */
cpumask_copy(policy->cpus, &cpu_present_map);
policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
return res;
}
static struct freq_attr *u8500_cpufreq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
};
static int u8500_cpu_exit(struct cpufreq_policy *policy)
{
cpufreq_frequency_table_put_attr(policy->cpu);
return 0;
}
static struct cpufreq_driver u8500_driver = {
.owner = THIS_MODULE,
.flags = CPUFREQ_STICKY,
.verify = u8500_cpufreq_verify_speed,
.target = u8500_cpufreq_target,
.get = u8500_cpufreq_getspeed,
.init = u8500_cpu_init,
.exit = u8500_cpu_exit,
.name = CPUFREQ_NAME,
.attr = u8500_cpufreq_attr,
static struct cpufreq_driver db8500_cpufreq_driver = {
.flags = CPUFREQ_STICKY,
.verify = db8500_cpufreq_verify_speed,
.target = db8500_cpufreq_target,
.get = db8500_cpufreq_getspeed,
.init = db8500_cpufreq_init,
.name = "DB8500",
.attr = db8500_cpufreq_attr,
};
static int __init u8500_cpufreq_probe(struct platform_device *pdev)
static int __init db8500_cpufreq_register(void)
{
dev = &pdev->dev;
return cpufreq_register_driver(&u8500_driver);
}
static int __exit u8500_cpufreq_remove(struct platform_device *pdev)
{
return cpufreq_unregister_driver(&u8500_driver);
}
if (!cpu_is_u8500v20_or_later())
return -ENODEV;
static struct platform_driver u8500_cpufreq_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
.remove = __exit_p(u8500_cpufreq_remove),
};
static int __init u8500_cpufreq_init(void)
{
return platform_driver_probe(&u8500_cpufreq_driver,
&u8500_cpufreq_probe);
pr_info("cpufreq for DB8500 started\n");
return cpufreq_register_driver(&db8500_cpufreq_driver);
}
device_initcall(u8500_cpufreq_init);
device_initcall(db8500_cpufreq_register);
......@@ -538,7 +538,7 @@ config AB8500_CORE
config AB8500_I2C_CORE
bool "AB8500 register access via PRCMU I2C"
depends on AB8500_CORE && UX500_SOC_DB8500
depends on AB8500_CORE && MFD_DB8500_PRCMU
default y
help
This enables register access to the AB8500 chip via PRCMU I2C.
......@@ -575,6 +575,26 @@ config AB3550_CORE
LEDs, vibrator, system power and temperature, power management
and ALSA sound.
config MFD_DB8500_PRCMU
bool "ST-Ericsson DB8500 Power Reset Control Management Unit"
depends on UX500_SOC_DB8500
select MFD_CORE
help
Select this option to enable support for the DB8500 Power Reset
and Control Management Unit. This is basically an autonomous
system controller running an XP70 microprocessor, which is accessed
through a register map.
config MFD_DB5500_PRCMU
bool "ST-Ericsson DB5500 Power Reset Control Management Unit"
depends on UX500_SOC_DB5500
select MFD_CORE
help
Select this option to enable support for the DB5500 Power Reset
and Control Management Unit. This is basically an autonomous
system controller running an XP70 microprocessor, which is accessed
through a register map.
config MFD_CS5535
tristate "Support for CS5535 and CS5536 southbridge core functions"
select MFD_CORE
......
......@@ -74,9 +74,12 @@ obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
obj-$(CONFIG_AB3550_CORE) += ab3550-core.o
obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o
obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o
obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
# ab8500-i2c need to come after db8500-prcmu (which provides the channel)
obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o
obj-$(CONFIG_MFD_DB5500_PRCMU) += db5500-prcmu.o
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
obj-$(CONFIG_LPC_SCH) += lpc_sch.o
......
......@@ -11,8 +11,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/ab8500.h>
#include <mach/prcmu.h>
#include <linux/mfd/db8500-prcmu.h>
static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data)
{
......
......@@ -15,11 +15,20 @@
#include <mach/hardware.h>
#define _PRCMU_BASE IO_ADDRESS(U8500_PRCMU_BASE)
#define PRCM_ARM_PLLDIVPS (_PRCMU_BASE + 0x118)
#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE 0x3f
#define PRCM_ARM_PLLDIVPS_MAX_MASK 0xf
#define PRCM_PLLARM_LOCKP (_PRCMU_BASE + 0x0a8)
#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 0x2
#define PRCM_ARM_CHGCLKREQ (_PRCMU_BASE + 0x114)
#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ 0x1
#define PRCM_PLLARM_ENABLE (_PRCMU_BASE + 0x98)
#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE 0x1
#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON 0x100
#define PRCM_ARMCLKFIX_MGT (_PRCMU_BASE + 0x0)
#define PRCM_A9_RESETN_CLR (_PRCMU_BASE + 0x1f4)
#define PRCM_A9_RESETN_SET (_PRCMU_BASE + 0x1f0)
......@@ -28,7 +37,8 @@
/* ARM WFI Standby signal register */
#define PRCM_ARM_WFI_STANDBY (_PRCMU_BASE + 0x130)
#define PRCMU_IOCR (_PRCMU_BASE + 0x310)
#define PRCM_IOCR (_PRCMU_BASE + 0x310)
#define PRCM_IOCR_IOFORCE 0x1
/* CPU mailbox registers */
#define PRCM_MBOX_CPU_VAL (_PRCMU_BASE + 0x0fc)
......@@ -37,6 +47,8 @@
/* Dual A9 core interrupt management unit registers */
#define PRCM_A9_MASK_REQ (_PRCMU_BASE + 0x328)
#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ 0x1
#define PRCM_A9_MASK_ACK (_PRCMU_BASE + 0x32c)
#define PRCM_ARMITMSK31TO0 (_PRCMU_BASE + 0x11c)
#define PRCM_ARMITMSK63TO32 (_PRCMU_BASE + 0x120)
......@@ -74,14 +86,17 @@
/* PRCMU clock/PLL/reset registers */
#define PRCM_PLLDSI_FREQ (_PRCMU_BASE + 0x500)
#define PRCM_PLLDSI_ENABLE (_PRCMU_BASE + 0x504)
#define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508)
#define PRCM_LCDCLK_MGT (_PRCMU_BASE + 0x044)
#define PRCM_MCDECLK_MGT (_PRCMU_BASE + 0x064)
#define PRCM_HDMICLK_MGT (_PRCMU_BASE + 0x058)
#define PRCM_TVCLK_MGT (_PRCMU_BASE + 0x07c)
#define PRCM_DSI_PLLOUT_SEL (_PRCMU_BASE + 0x530)
#define PRCM_DSITVCLK_DIV (_PRCMU_BASE + 0x52C)
#define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508)
#define PRCM_APE_RESETN_SET (_PRCMU_BASE + 0x1E4)
#define PRCM_APE_RESETN_CLR (_PRCMU_BASE + 0x1E8)
#define PRCM_CLKOCR (_PRCMU_BASE + 0x1CC)
/* ePOD and memory power signal control registers */
#define PRCM_EPOD_C_SET (_PRCMU_BASE + 0x410)
......@@ -92,5 +107,9 @@
/* Miscellaneous unit registers */
#define PRCM_DSI_SW_RESET (_PRCMU_BASE + 0x324)
#define PRCM_GPIOCR (_PRCMU_BASE + 0x138)
#define PRCM_GPIOCR_DBG_STM_MOD_CMD1 0x800
#define PRCM_GPIOCR_DBG_UARTMOD_CMD0 0x1
#endif /* __MACH_PRCMU_REGS_H */
#endif /* __MACH_PRCMU__REGS_H */
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
* Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
*
* U5500 PRCM Unit interface driver
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/completion.h>
#include <linux/irq.h>
#include <linux/jiffies.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/mfd/db5500-prcmu.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <mach/db5500-regs.h>
#include "db5500-prcmu-regs.h"
#define _PRCM_MB_HEADER (tcdm_base + 0xFE8)
#define PRCM_REQ_MB0_HEADER (_PRCM_MB_HEADER + 0x0)
#define PRCM_REQ_MB1_HEADER (_PRCM_MB_HEADER + 0x1)
#define PRCM_REQ_MB2_HEADER (_PRCM_MB_HEADER + 0x2)
#define PRCM_REQ_MB3_HEADER (_PRCM_MB_HEADER + 0x3)
#define PRCM_REQ_MB4_HEADER (_PRCM_MB_HEADER + 0x4)
#define PRCM_REQ_MB5_HEADER (_PRCM_MB_HEADER + 0x5)
#define PRCM_REQ_MB6_HEADER (_PRCM_MB_HEADER + 0x6)
#define PRCM_REQ_MB7_HEADER (_PRCM_MB_HEADER + 0x7)
#define PRCM_ACK_MB0_HEADER (_PRCM_MB_HEADER + 0x8)
#define PRCM_ACK_MB1_HEADER (_PRCM_MB_HEADER + 0x9)
#define PRCM_ACK_MB2_HEADER (_PRCM_MB_HEADER + 0xa)
#define PRCM_ACK_MB3_HEADER (_PRCM_MB_HEADER + 0xb)
#define PRCM_ACK_MB4_HEADER (_PRCM_MB_HEADER + 0xc)
#define PRCM_ACK_MB5_HEADER (_PRCM_MB_HEADER + 0xd)
#define PRCM_ACK_MB6_HEADER (_PRCM_MB_HEADER + 0xe)
#define PRCM_ACK_MB7_HEADER (_PRCM_MB_HEADER + 0xf)
/* Req Mailboxes */
#define PRCM_REQ_MB0 (tcdm_base + 0xFD8)
#define PRCM_REQ_MB1 (tcdm_base + 0xFCC)
#define PRCM_REQ_MB2 (tcdm_base + 0xFC4)
#define PRCM_REQ_MB3 (tcdm_base + 0xFC0)
#define PRCM_REQ_MB4 (tcdm_base + 0xF98)
#define PRCM_REQ_MB5 (tcdm_base + 0xF90)
#define PRCM_REQ_MB6 (tcdm_base + 0xF8C)
#define PRCM_REQ_MB7 (tcdm_base + 0xF84)
/* Ack Mailboxes */
#define PRCM_ACK_MB0 (tcdm_base + 0xF38)
#define PRCM_ACK_MB1 (tcdm_base + 0xF30)
#define PRCM_ACK_MB2 (tcdm_base + 0xF24)
#define PRCM_ACK_MB3 (tcdm_base + 0xF20)
#define PRCM_ACK_MB4 (tcdm_base + 0xF1C)
#define PRCM_ACK_MB5 (tcdm_base + 0xF14)
#define PRCM_ACK_MB6 (tcdm_base + 0xF0C)
#define PRCM_ACK_MB7 (tcdm_base + 0xF08)
enum mb_return_code {
RC_SUCCESS,
RC_FAIL,
};
/* Mailbox 0 headers. */
enum mb0_header {
/* request */
RMB0H_PWR_STATE_TRANS = 1,
RMB0H_WAKE_UP_CFG,
RMB0H_RD_WAKE_UP_ACK,
/* acknowledge */
AMB0H_WAKE_UP = 1,
};
/* Mailbox 5 headers. */
enum mb5_header {
MB5H_I2C_WRITE = 1,
MB5H_I2C_READ,
};
/* Request mailbox 5 fields. */
#define PRCM_REQ_MB5_I2C_SLAVE (PRCM_REQ_MB5 + 0)
#define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 1)
#define PRCM_REQ_MB5_I2C_SIZE (PRCM_REQ_MB5 + 2)
#define PRCM_REQ_MB5_I2C_DATA (PRCM_REQ_MB5 + 4)
/* Acknowledge mailbox 5 fields. */
#define PRCM_ACK_MB5_RETURN_CODE (PRCM_ACK_MB5 + 0)
#define PRCM_ACK_MB5_I2C_DATA (PRCM_ACK_MB5 + 4)
#define NUM_MB 8
#define MBOX_BIT BIT
#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1)
/*
* Used by MCDE to setup all necessary PRCMU registers
*/
#define PRCMU_RESET_DSIPLL 0x00004000
#define PRCMU_UNCLAMP_DSIPLL 0x00400800
/* HDMI CLK MGT PLLSW=001 (PLLSOC0), PLLDIV=0x8, = 50 Mhz*/
#define PRCMU_DSI_CLOCK_SETTING 0x00000128
/* TVCLK_MGT PLLSW=001 (PLLSOC0) PLLDIV=0x13, = 19.05 MHZ */
#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000135
#define PRCMU_PLLDSI_FREQ_SETTING 0x0004013C
#define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000002
#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x03000101
#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00000101
#define PRCMU_ENABLE_PLLDSI 0x00000001
#define PRCMU_DISABLE_PLLDSI 0x00000000
#define PRCMU_DSI_RESET_SW 0x00000003
#define PRCMU_PLLDSI_LOCKP_LOCKED 0x3
/*
* mb0_transfer - state needed for mailbox 0 communication.
* @lock: The transaction lock.
*/
static struct {
spinlock_t lock;
} mb0_transfer;
/*
* mb5_transfer - state needed for mailbox 5 communication.
* @lock: The transaction lock.
* @work: The transaction completion structure.
* @ack: Reply ("acknowledge") data.
*/
static struct {
struct mutex lock;
struct completion work;
struct {
u8 header;
u8 status;
u8 value[4];
} ack;
} mb5_transfer;
/* PRCMU TCDM base IO address. */
static __iomem void *tcdm_base;
/**
* db5500_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).
* @size: The number of registers to read.
*
* Reads register value(s) from the ABB.
* @size has to be <= 4.
*/
int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
{
int r;
if ((size < 1) || (4 < size))
return -EINVAL;
mutex_lock(&mb5_transfer.lock);
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
cpu_relax();
writeb(slave, PRCM_REQ_MB5_I2C_SLAVE);
writeb(reg, PRCM_REQ_MB5_I2C_REG);
writeb(size, PRCM_REQ_MB5_I2C_SIZE);
writeb(MB5H_I2C_READ, PRCM_REQ_MB5_HEADER);
writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
wait_for_completion(&mb5_transfer.work);
r = 0;
if ((mb5_transfer.ack.header == MB5H_I2C_READ) &&
(mb5_transfer.ack.status == RC_SUCCESS))
memcpy(value, mb5_transfer.ack.value, (size_t)size);
else
r = -EIO;
mutex_unlock(&mb5_transfer.lock);
return r;
}
/**
* db5500_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.
* @size: The number of registers to write.
*
* Writes register value(s) to the ABB.
* @size has to be <= 4.
*/
int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
{
int r;
if ((size < 1) || (4 < size))
return -EINVAL;
mutex_lock(&mb5_transfer.lock);
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
cpu_relax();
writeb(slave, PRCM_REQ_MB5_I2C_SLAVE);
writeb(reg, PRCM_REQ_MB5_I2C_REG);
writeb(size, PRCM_REQ_MB5_I2C_SIZE);
memcpy_toio(PRCM_REQ_MB5_I2C_DATA, value, size);
writeb(MB5H_I2C_WRITE, PRCM_REQ_MB5_HEADER);
writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
wait_for_completion(&mb5_transfer.work);
if ((mb5_transfer.ack.header == MB5H_I2C_WRITE) &&
(mb5_transfer.ack.status == RC_SUCCESS))
r = 0;
else
r = -EIO;
mutex_unlock(&mb5_transfer.lock);
return r;
}
int db5500_prcmu_enable_dsipll(void)
{
int i;
/* Enable DSIPLL_RESETN resets */
writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR);
/* Unclamp DSIPLL in/out */
writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR);
/* Set DSI PLL FREQ */
writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ);
writel(PRCMU_DSI_PLLOUT_SEL_SETTING,
PRCM_DSI_PLLOUT_SEL);
/* Enable Escape clocks */
writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
/* Start DSI PLL */
writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
/* Reset DSI PLL */
writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET);
for (i = 0; i < 10; i++) {
if ((readl(PRCM_PLLDSI_LOCKP) &
PRCMU_PLLDSI_LOCKP_LOCKED) == PRCMU_PLLDSI_LOCKP_LOCKED)
break;
udelay(100);
}
/* Release DSIPLL_RESETN */
writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_SET);
return 0;
}
int db5500_prcmu_disable_dsipll(void)
{
/* Disable dsi pll */
writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
/* Disable escapeclock */
writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
return 0;
}
int db5500_prcmu_set_display_clocks(void)
{
/* HDMI and TVCLK Should be handled somewhere else */
/* PLLDIV=8, PLLSW=2, CLKEN=1 */
writel(PRCMU_DSI_CLOCK_SETTING, PRCM_HDMICLK_MGT);
/* PLLDIV=14, PLLSW=2, CLKEN=1 */
writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT);
return 0;
}
static void ack_dbb_wakeup(void)
{
unsigned long flags;
spin_lock_irqsave(&mb0_transfer.lock, flags);
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
cpu_relax();
writeb(RMB0H_RD_WAKE_UP_ACK, PRCM_REQ_MB0_HEADER);
writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
spin_unlock_irqrestore(&mb0_transfer.lock, flags);
}
static inline void print_unknown_header_warning(u8 n, u8 header)
{
pr_warning("prcmu: Unknown message header (%d) in mailbox %d.\n",
header, n);
}
static bool read_mailbox_0(void)
{
bool r;
u8 header;
header = readb(PRCM_ACK_MB0_HEADER);
switch (header) {
case AMB0H_WAKE_UP:
r = true;
break;
default:
print_unknown_header_warning(0, header);
r = false;
break;
}
writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
return r;
}
static bool read_mailbox_1(void)
{
writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
return false;
}
static bool read_mailbox_2(void)
{
writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR);
return false;
}
static bool read_mailbox_3(void)
{
writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR);
return false;
}
static bool read_mailbox_4(void)
{
writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR);
return false;
}
static bool read_mailbox_5(void)
{
u8 header;
header = readb(PRCM_ACK_MB5_HEADER);
switch (header) {
case MB5H_I2C_READ:
memcpy_fromio(mb5_transfer.ack.value, PRCM_ACK_MB5_I2C_DATA, 4);
case MB5H_I2C_WRITE:
mb5_transfer.ack.header = header;
mb5_transfer.ack.status = readb(PRCM_ACK_MB5_RETURN_CODE);
complete(&mb5_transfer.work);
break;
default:
print_unknown_header_warning(5, header);
break;
}
writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR);
return false;
}
static bool read_mailbox_6(void)
{
writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR);
return false;
}
static bool read_mailbox_7(void)
{
writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR);
return false;
}
static bool (* const read_mailbox[NUM_MB])(void) = {
read_mailbox_0,
read_mailbox_1,
read_mailbox_2,
read_mailbox_3,
read_mailbox_4,
read_mailbox_5,
read_mailbox_6,
read_mailbox_7
};
static irqreturn_t prcmu_irq_handler(int irq, void *data)
{
u32 bits;
u8 n;
irqreturn_t r;
bits = (readl(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
if (unlikely(!bits))
return IRQ_NONE;
r = IRQ_HANDLED;
for (n = 0; bits; n++) {
if (bits & MBOX_BIT(n)) {
bits -= MBOX_BIT(n);
if (read_mailbox[n]())
r = IRQ_WAKE_THREAD;
}
}
return r;
}
static irqreturn_t prcmu_irq_thread_fn(int irq, void *data)
{
ack_dbb_wakeup();
return IRQ_HANDLED;
}
void __init db5500_prcmu_early_init(void)
{
tcdm_base = __io_address(U5500_PRCMU_TCDM_BASE);
spin_lock_init(&mb0_transfer.lock);
mutex_init(&mb5_transfer.lock);
init_completion(&mb5_transfer.work);
}
/**
* prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
*
*/
int __init db5500_prcmu_init(void)
{
int r = 0;
if (ux500_is_svp() || !cpu_is_u5500())
return -ENODEV;
/* Clean up the mailbox interrupts after pre-kernel code. */
writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLEAR);
r = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler,
prcmu_irq_thread_fn, 0, "prcmu", NULL);
if (r < 0) {
pr_err("prcmu: Failed to allocate IRQ_DB5500_PRCMU1.\n");
return -EBUSY;
}
return 0;
}
arch_initcall(db5500_prcmu_init);
/*
* Copyright (C) STMicroelectronics 2009
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
* Author: Sundar Iyer <sundar.iyer@stericsson.com>
*
* License Terms: GNU General Public License v2
*
* PRCM Unit registers
*/
#ifndef __DB8500_PRCMU_REGS_H
#define __DB8500_PRCMU_REGS_H
#include <linux/bitops.h>
#include <mach/hardware.h>
#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))
#define PRCM_ARM_PLLDIVPS 0x118
#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE BITS(0, 5)
#define PRCM_ARM_PLLDIVPS_MAX_MASK 0xF
#define PRCM_PLLARM_LOCKP 0x0A8
#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 BIT(1)
#define PRCM_ARM_CHGCLKREQ 0x114
#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ BIT(0)
#define PRCM_PLLARM_ENABLE 0x98
#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE BIT(0)
#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON BIT(8)
#define PRCM_ARMCLKFIX_MGT 0x0
#define PRCM_A9_RESETN_CLR 0x1f4
#define PRCM_A9_RESETN_SET 0x1f0
#define PRCM_ARM_LS_CLAMP 0x30C
#define PRCM_SRAM_A9 0x308
/* ARM WFI Standby signal register */
#define PRCM_ARM_WFI_STANDBY 0x130
#define PRCM_IOCR 0x310
#define PRCM_IOCR_IOFORCE BIT(0)
/* CPU mailbox registers */
#define PRCM_MBOX_CPU_VAL 0x0FC
#define PRCM_MBOX_CPU_SET 0x100
/* Dual A9 core interrupt management unit registers */
#define PRCM_A9_MASK_REQ 0x328
#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ BIT(0)
#define PRCM_A9_MASK_ACK 0x32C
#define PRCM_ARMITMSK31TO0 0x11C
#define PRCM_ARMITMSK63TO32 0x120
#define PRCM_ARMITMSK95TO64 0x124
#define PRCM_ARMITMSK127TO96 0x128
#define PRCM_POWER_STATE_VAL 0x25C
#define PRCM_ARMITVAL31TO0 0x260
#define PRCM_ARMITVAL63TO32 0x264
#define PRCM_ARMITVAL95TO64 0x268
#define PRCM_ARMITVAL127TO96 0x26C
#define PRCM_HOSTACCESS_REQ 0x334
#define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ BIT(0)
#define PRCM_ARM_IT1_CLR 0x48C
#define PRCM_ARM_IT1_VAL 0x494
#define PRCM_ITSTATUS0 0x148
#define PRCM_ITSTATUS1 0x150
#define PRCM_ITSTATUS2 0x158
#define PRCM_ITSTATUS3 0x160
#define PRCM_ITSTATUS4 0x168
#define PRCM_ITSTATUS5 0x484
#define PRCM_ITCLEAR5 0x488
#define PRCM_ARMIT_MASKXP70_IT 0x1018
/* System reset register */
#define PRCM_APE_SOFTRST 0x228
/* Level shifter and clamp control registers */
#define PRCM_MMIP_LS_CLAMP_SET 0x420
#define PRCM_MMIP_LS_CLAMP_CLR 0x424
/* PRCMU HW semaphore */
#define PRCM_SEM 0x400
#define PRCM_SEM_PRCM_SEM BIT(0)
/* PRCMU clock/PLL/reset registers */
#define PRCM_PLLDSI_FREQ 0x500
#define PRCM_PLLDSI_ENABLE 0x504
#define PRCM_PLLDSI_LOCKP 0x508
#define PRCM_DSI_PLLOUT_SEL 0x530
#define PRCM_DSITVCLK_DIV 0x52C
#define PRCM_APE_RESETN_SET 0x1E4
#define PRCM_APE_RESETN_CLR 0x1E8
#define PRCM_TCR 0x1C8
#define PRCM_TCR_TENSEL_MASK BITS(0, 7)
#define PRCM_TCR_STOP_TIMERS BIT(16)
#define PRCM_TCR_DOZE_MODE BIT(17)
#define PRCM_CLKOCR 0x1CC
#define PRCM_CLKOCR_CLKODIV0_SHIFT 0
#define PRCM_CLKOCR_CLKODIV0_MASK BITS(0, 5)
#define PRCM_CLKOCR_CLKOSEL0_SHIFT 6
#define PRCM_CLKOCR_CLKOSEL0_MASK BITS(6, 8)
#define PRCM_CLKOCR_CLKODIV1_SHIFT 16
#define PRCM_CLKOCR_CLKODIV1_MASK BITS(16, 21)
#define PRCM_CLKOCR_CLKOSEL1_SHIFT 22
#define PRCM_CLKOCR_CLKOSEL1_MASK BITS(22, 24)
#define PRCM_CLKOCR_CLK1TYPE BIT(28)
#define PRCM_SGACLK_MGT 0x014
#define PRCM_UARTCLK_MGT 0x018
#define PRCM_MSP02CLK_MGT 0x01C
#define PRCM_MSP1CLK_MGT 0x288
#define PRCM_I2CCLK_MGT 0x020
#define PRCM_SDMMCCLK_MGT 0x024
#define PRCM_SLIMCLK_MGT 0x028
#define PRCM_PER1CLK_MGT 0x02C
#define PRCM_PER2CLK_MGT 0x030
#define PRCM_PER3CLK_MGT 0x034
#define PRCM_PER5CLK_MGT 0x038
#define PRCM_PER6CLK_MGT 0x03C
#define PRCM_PER7CLK_MGT 0x040
#define PRCM_LCDCLK_MGT 0x044
#define PRCM_BMLCLK_MGT 0x04C
#define PRCM_HSITXCLK_MGT 0x050
#define PRCM_HSIRXCLK_MGT 0x054
#define PRCM_HDMICLK_MGT 0x058
#define PRCM_APEATCLK_MGT 0x05C
#define PRCM_APETRACECLK_MGT 0x060
#define PRCM_MCDECLK_MGT 0x064
#define PRCM_IPI2CCLK_MGT 0x068
#define PRCM_DSIALTCLK_MGT 0x06C
#define PRCM_DMACLK_MGT 0x074
#define PRCM_B2R2CLK_MGT 0x078
#define PRCM_TVCLK_MGT 0x07C
#define PRCM_UNIPROCLK_MGT 0x278
#define PRCM_SSPCLK_MGT 0x280
#define PRCM_RNGCLK_MGT 0x284
#define PRCM_UICCCLK_MGT 0x27C
#define PRCM_CLK_MGT_CLKPLLDIV_MASK BITS(0, 4)
#define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7)
#define PRCM_CLK_MGT_CLKEN BIT(8)
/* ePOD and memory power signal control registers */
#define PRCM_EPOD_C_SET 0x410
#define PRCM_SRAM_LS_SLEEP 0x304
/* Debug power control unit registers */
#define PRCM_POWER_STATE_SET 0x254
/* Miscellaneous unit registers */
#define PRCM_DSI_SW_RESET 0x324
#define PRCM_GPIOCR 0x138
/* GPIOCR register */
#define PRCM_GPIOCR_SPI2_SELECT BIT(23)
#define PRCM_DDR_SUBSYS_APE_MINBW 0x438
#endif /* __DB8500_PRCMU_REGS_H */
此差异已折叠。
......@@ -274,6 +274,13 @@ config REGULATOR_AB8500
This driver supports the regulators found on the ST-Ericsson mixed
signal AB8500 PMIC
config REGULATOR_DB8500_PRCMU
bool "ST-Ericsson DB8500 Voltage Domain Regulators"
depends on MFD_DB8500_PRCMU
help
This driver supports the voltage domain regulators controlled by the
DB8500 PRCMU
config REGULATOR_TPS6586X
tristate "TI TPS6586X Power regulators"
depends on MFD_TPS6586X
......
......@@ -41,5 +41,6 @@ obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
* Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
* Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
*
* Power domain regulators on DB8500
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/db8500-prcmu.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/db8500-prcmu.h>
/*
* power state reference count
*/
static int power_state_active_cnt; /* will initialize to zero */
static DEFINE_SPINLOCK(power_state_active_lock);
static void power_state_active_enable(void)
{
unsigned long flags;
spin_lock_irqsave(&power_state_active_lock, flags);
power_state_active_cnt++;
spin_unlock_irqrestore(&power_state_active_lock, flags);
}
static int power_state_active_disable(void)
{
int ret = 0;
unsigned long flags;
spin_lock_irqsave(&power_state_active_lock, flags);
if (power_state_active_cnt <= 0) {
pr_err("power state: unbalanced enable/disable calls\n");
ret = -EINVAL;
goto out;
}
power_state_active_cnt--;
out:
spin_unlock_irqrestore(&power_state_active_lock, flags);
return ret;
}
/*
* Exported interface for CPUIdle only. This function is called when interrupts
* are turned off. Hence, no locking.
*/
int power_state_active_is_enabled(void)
{
return (power_state_active_cnt > 0);
}
/**
* struct db8500_regulator_info - db8500 regulator information
* @dev: device pointer
* @desc: regulator description
* @rdev: regulator device pointer
* @is_enabled: status of the regulator
* @epod_id: id for EPOD (power domain)
* @is_ramret: RAM retention switch for EPOD (power domain)
* @operating_point: operating point (only for vape, to be removed)
*
*/
struct db8500_regulator_info {
struct device *dev;
struct regulator_desc desc;
struct regulator_dev *rdev;
bool is_enabled;
u16 epod_id;
bool is_ramret;
bool exclude_from_power_state;
unsigned int operating_point;
};
static int db8500_regulator_enable(struct regulator_dev *rdev)
{
struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
if (info == NULL)
return -EINVAL;
dev_vdbg(rdev_get_dev(rdev), "regulator-%s-enable\n",
info->desc.name);
info->is_enabled = true;
if (!info->exclude_from_power_state)
power_state_active_enable();
return 0;
}
static int db8500_regulator_disable(struct regulator_dev *rdev)
{
struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
int ret = 0;
if (info == NULL)
return -EINVAL;
dev_vdbg(rdev_get_dev(rdev), "regulator-%s-disable\n",
info->desc.name);
info->is_enabled = false;
if (!info->exclude_from_power_state)
ret = power_state_active_disable();
return ret;
}
static int db8500_regulator_is_enabled(struct regulator_dev *rdev)
{
struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
if (info == NULL)
return -EINVAL;
dev_vdbg(rdev_get_dev(rdev), "regulator-%s-is_enabled (is_enabled):"
" %i\n", info->desc.name, info->is_enabled);
return info->is_enabled;
}
/* db8500 regulator operations */
static struct regulator_ops db8500_regulator_ops = {
.enable = db8500_regulator_enable,
.disable = db8500_regulator_disable,
.is_enabled = db8500_regulator_is_enabled,
};
/*
* EPOD control
*/
static bool epod_on[NUM_EPOD_ID];
static bool epod_ramret[NUM_EPOD_ID];
static int enable_epod(u16 epod_id, bool ramret)
{
int ret;
if (ramret) {
if (!epod_on[epod_id]) {
ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
if (ret < 0)
return ret;
}
epod_ramret[epod_id] = true;
} else {
ret = prcmu_set_epod(epod_id, EPOD_STATE_ON);
if (ret < 0)
return ret;
epod_on[epod_id] = true;
}
return 0;
}
static int disable_epod(u16 epod_id, bool ramret)
{
int ret;
if (ramret) {
if (!epod_on[epod_id]) {
ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
if (ret < 0)
return ret;
}
epod_ramret[epod_id] = false;
} else {
if (epod_ramret[epod_id]) {
ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
if (ret < 0)
return ret;
} else {
ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
if (ret < 0)
return ret;
}
epod_on[epod_id] = false;
}
return 0;
}
/*
* Regulator switch
*/
static int db8500_regulator_switch_enable(struct regulator_dev *rdev)
{
struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
int ret;
if (info == NULL)
return -EINVAL;
dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-enable\n",
info->desc.name);
ret = enable_epod(info->epod_id, info->is_ramret);
if (ret < 0) {
dev_err(rdev_get_dev(rdev),
"regulator-switch-%s-enable: prcmu call failed\n",
info->desc.name);
goto out;
}
info->is_enabled = true;
out:
return ret;
}
static int db8500_regulator_switch_disable(struct regulator_dev *rdev)
{
struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
int ret;
if (info == NULL)
return -EINVAL;
dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-disable\n",
info->desc.name);
ret = disable_epod(info->epod_id, info->is_ramret);
if (ret < 0) {
dev_err(rdev_get_dev(rdev),
"regulator_switch-%s-disable: prcmu call failed\n",
info->desc.name);
goto out;
}
info->is_enabled = 0;
out:
return ret;
}
static int db8500_regulator_switch_is_enabled(struct regulator_dev *rdev)
{
struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
if (info == NULL)
return -EINVAL;
dev_vdbg(rdev_get_dev(rdev),
"regulator-switch-%s-is_enabled (is_enabled): %i\n",
info->desc.name, info->is_enabled);
return info->is_enabled;
}
static struct regulator_ops db8500_regulator_switch_ops = {
.enable = db8500_regulator_switch_enable,
.disable = db8500_regulator_switch_disable,
.is_enabled = db8500_regulator_switch_is_enabled,
};
/*
* Regulator information
*/
static struct db8500_regulator_info
db8500_regulator_info[DB8500_NUM_REGULATORS] = {
[DB8500_REGULATOR_VAPE] = {
.desc = {
.name = "db8500-vape",
.id = DB8500_REGULATOR_VAPE,
.ops = &db8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
},
[DB8500_REGULATOR_VARM] = {
.desc = {
.name = "db8500-varm",
.id = DB8500_REGULATOR_VARM,
.ops = &db8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
},
[DB8500_REGULATOR_VMODEM] = {
.desc = {
.name = "db8500-vmodem",
.id = DB8500_REGULATOR_VMODEM,
.ops = &db8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
},
[DB8500_REGULATOR_VPLL] = {
.desc = {
.name = "db8500-vpll",
.id = DB8500_REGULATOR_VPLL,
.ops = &db8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
},
[DB8500_REGULATOR_VSMPS1] = {
.desc = {
.name = "db8500-vsmps1",
.id = DB8500_REGULATOR_VSMPS1,
.ops = &db8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
},
[DB8500_REGULATOR_VSMPS2] = {
.desc = {
.name = "db8500-vsmps2",
.id = DB8500_REGULATOR_VSMPS2,
.ops = &db8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.exclude_from_power_state = true,
},
[DB8500_REGULATOR_VSMPS3] = {
.desc = {
.name = "db8500-vsmps3",
.id = DB8500_REGULATOR_VSMPS3,
.ops = &db8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
},
[DB8500_REGULATOR_VRF1] = {
.desc = {
.name = "db8500-vrf1",
.id = DB8500_REGULATOR_VRF1,
.ops = &db8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
},
[DB8500_REGULATOR_SWITCH_SVAMMDSP] = {
.desc = {
.name = "db8500-sva-mmdsp",
.id = DB8500_REGULATOR_SWITCH_SVAMMDSP,
.ops = &db8500_regulator_switch_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.epod_id = EPOD_ID_SVAMMDSP,
},
[DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = {
.desc = {
.name = "db8500-sva-mmdsp-ret",
.id = DB8500_REGULATOR_SWITCH_SVAMMDSPRET,
.ops = &db8500_regulator_switch_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.epod_id = EPOD_ID_SVAMMDSP,
.is_ramret = true,
},
[DB8500_REGULATOR_SWITCH_SVAPIPE] = {
.desc = {
.name = "db8500-sva-pipe",
.id = DB8500_REGULATOR_SWITCH_SVAPIPE,
.ops = &db8500_regulator_switch_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.epod_id = EPOD_ID_SVAPIPE,
},
[DB8500_REGULATOR_SWITCH_SIAMMDSP] = {
.desc = {
.name = "db8500-sia-mmdsp",
.id = DB8500_REGULATOR_SWITCH_SIAMMDSP,
.ops = &db8500_regulator_switch_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.epod_id = EPOD_ID_SIAMMDSP,
},
[DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = {
.desc = {
.name = "db8500-sia-mmdsp-ret",
.id = DB8500_REGULATOR_SWITCH_SIAMMDSPRET,
.ops = &db8500_regulator_switch_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.epod_id = EPOD_ID_SIAMMDSP,
.is_ramret = true,
},
[DB8500_REGULATOR_SWITCH_SIAPIPE] = {
.desc = {
.name = "db8500-sia-pipe",
.id = DB8500_REGULATOR_SWITCH_SIAPIPE,
.ops = &db8500_regulator_switch_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.epod_id = EPOD_ID_SIAPIPE,
},
[DB8500_REGULATOR_SWITCH_SGA] = {
.desc = {
.name = "db8500-sga",
.id = DB8500_REGULATOR_SWITCH_SGA,
.ops = &db8500_regulator_switch_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.epod_id = EPOD_ID_SGA,
},
[DB8500_REGULATOR_SWITCH_B2R2_MCDE] = {
.desc = {
.name = "db8500-b2r2-mcde",
.id = DB8500_REGULATOR_SWITCH_B2R2_MCDE,
.ops = &db8500_regulator_switch_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.epod_id = EPOD_ID_B2R2_MCDE,
},
[DB8500_REGULATOR_SWITCH_ESRAM12] = {
.desc = {
.name = "db8500-esram12",
.id = DB8500_REGULATOR_SWITCH_ESRAM12,
.ops = &db8500_regulator_switch_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.epod_id = EPOD_ID_ESRAM12,
.is_enabled = true,
},
[DB8500_REGULATOR_SWITCH_ESRAM12RET] = {
.desc = {
.name = "db8500-esram12-ret",
.id = DB8500_REGULATOR_SWITCH_ESRAM12RET,
.ops = &db8500_regulator_switch_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.epod_id = EPOD_ID_ESRAM12,
.is_ramret = true,
},
[DB8500_REGULATOR_SWITCH_ESRAM34] = {
.desc = {
.name = "db8500-esram34",
.id = DB8500_REGULATOR_SWITCH_ESRAM34,
.ops = &db8500_regulator_switch_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.epod_id = EPOD_ID_ESRAM34,
.is_enabled = true,
},
[DB8500_REGULATOR_SWITCH_ESRAM34RET] = {
.desc = {
.name = "db8500-esram34-ret",
.id = DB8500_REGULATOR_SWITCH_ESRAM34RET,
.ops = &db8500_regulator_switch_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
.epod_id = EPOD_ID_ESRAM34,
.is_ramret = true,
},
};
static int __devinit db8500_regulator_probe(struct platform_device *pdev)
{
struct regulator_init_data *db8500_init_data = mfd_get_data(pdev);
int i, err;
/* register all regulators */
for (i = 0; i < ARRAY_SIZE(db8500_regulator_info); i++) {
struct db8500_regulator_info *info;
struct regulator_init_data *init_data = &db8500_init_data[i];
/* assign per-regulator data */
info = &db8500_regulator_info[i];
info->dev = &pdev->dev;
/* register with the regulator framework */
info->rdev = regulator_register(&info->desc, &pdev->dev,
init_data, info);
if (IS_ERR(info->rdev)) {
err = PTR_ERR(info->rdev);
dev_err(&pdev->dev, "failed to register %s: err %i\n",
info->desc.name, err);
/* if failing, unregister all earlier regulators */
i--;
while (i >= 0) {
info = &db8500_regulator_info[i];
regulator_unregister(info->rdev);
i--;
}
return err;
}
dev_dbg(rdev_get_dev(info->rdev),
"regulator-%s-probed\n", info->desc.name);
}
return 0;
}
static int __exit db8500_regulator_remove(struct platform_device *pdev)
{
int i;
for (i = 0; i < ARRAY_SIZE(db8500_regulator_info); i++) {
struct db8500_regulator_info *info;
info = &db8500_regulator_info[i];
dev_vdbg(rdev_get_dev(info->rdev),
"regulator-%s-remove\n", info->desc.name);
regulator_unregister(info->rdev);
}
return 0;
}
static struct platform_driver db8500_regulator_driver = {
.driver = {
.name = "db8500-prcmu-regulators",
.owner = THIS_MODULE,
},
.probe = db8500_regulator_probe,
.remove = __exit_p(db8500_regulator_remove),
};
static int __init db8500_regulator_init(void)
{
int ret;
ret = platform_driver_register(&db8500_regulator_driver);
if (ret < 0)
return -ENODEV;
return 0;
}
static void __exit db8500_regulator_exit(void)
{
platform_driver_unregister(&db8500_regulator_driver);
}
arch_initcall(db8500_regulator_init);
module_exit(db8500_regulator_exit);
MODULE_AUTHOR("STMicroelectronics/ST-Ericsson");
MODULE_DESCRIPTION("DB8500 regulator driver");
MODULE_LICENSE("GPL v2");
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
*
* U5500 PRCMU API.
*/
#ifndef __MACH_PRCMU_U5500_H
#define __MACH_PRCMU_U5500_H
#ifdef CONFIG_UX500_SOC_DB5500
void db5500_prcmu_early_init(void);
int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
#else /* !CONFIG_UX500_SOC_DB5500 */
static inline void db5500_prcmu_early_init(void)
{
}
static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
{
return -ENOSYS;
}
static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
{
return -ENOSYS;
}
#endif /* CONFIG_UX500_SOC_DB5500 */
static inline int db5500_prcmu_config_abb_event_readout(u32 abb_events)
{
#ifdef CONFIG_MACH_U5500_SIMULATOR
return 0;
#else
return -1;
#endif
}
#endif /* __MACH_PRCMU_U5500_H */
此差异已折叠。
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
*
* Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
*
* Interface to power domain regulators on DB8500
*/
#ifndef __REGULATOR_H__
#define __REGULATOR_H__
/* Number of DB8500 regulators and regulator enumeration */
enum db8500_regulator_id {
DB8500_REGULATOR_VAPE,
DB8500_REGULATOR_VARM,
DB8500_REGULATOR_VMODEM,
DB8500_REGULATOR_VPLL,
DB8500_REGULATOR_VSMPS1,
DB8500_REGULATOR_VSMPS2,
DB8500_REGULATOR_VSMPS3,
DB8500_REGULATOR_VRF1,
DB8500_REGULATOR_SWITCH_SVAMMDSP,
DB8500_REGULATOR_SWITCH_SVAMMDSPRET,
DB8500_REGULATOR_SWITCH_SVAPIPE,
DB8500_REGULATOR_SWITCH_SIAMMDSP,
DB8500_REGULATOR_SWITCH_SIAMMDSPRET,
DB8500_REGULATOR_SWITCH_SIAPIPE,
DB8500_REGULATOR_SWITCH_SGA,
DB8500_REGULATOR_SWITCH_B2R2_MCDE,
DB8500_REGULATOR_SWITCH_ESRAM12,
DB8500_REGULATOR_SWITCH_ESRAM12RET,
DB8500_REGULATOR_SWITCH_ESRAM34,
DB8500_REGULATOR_SWITCH_ESRAM34RET,
DB8500_NUM_REGULATORS
};
/*
* Exported interface for CPUIdle only. This function is called with all
* interrupts turned off.
*/
int power_state_active_is_enabled(void);
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册