aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/db8500-prcmu.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-02 12:38:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-02 12:38:16 -0400
commit99c6bcf46d2233d33e441834e958ed0bc22b190a (patch)
tree25abf5e856bc0f08d75e623715eb5acc4d4de2b2 /drivers/mfd/db8500-prcmu.c
parent97b1007a2924aaa9126398623f6755a8c3c6a616 (diff)
parent2fdfe1c26fb9f24cfdf124384abb35396ca2cd3f (diff)
Merge tag 'multiplatform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC multiplatform updates from Olof Johansson: "More multiplatform enablement for ARM platforms. The ones converted in this branch are: - bcm2835 - cns3xxx - sirf - nomadik - msx - spear - tegra - ux500 We're getting close to having most of them converted! One of the larger platforms remaining is Samsung Exynos, and there are a bunch of supporting patches in this merge window for it. There was a patch in this branch to a early version of multiplatform conversion, but it ended up being reverted due to need of more bake time. The revert commit is part of the branch since it would have required rebasing multiple dependent branches and they were stable by then" * tag 'multiplatform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (70 commits) mmc: sdhci-s3c: Fix operation on non-single image Samsung platforms clocksource: nomadik-mtu: fix up clocksource/timer Revert "ARM: exynos: enable multiplatform support" ARM: SPEAr13xx: Fix typo "ARCH_HAVE_CPUFREQ" ARM: exynos: enable multiplatform support rtc: s3c: make header file local mtd: onenand/samsung: make regs-onenand.h file local thermal/exynos: remove unnecessary header inclusions mmc: sdhci-s3c: remove platform dependencies ARM: samsung: move mfc device definition to s5p-dev-mfc.c ARM: exynos: move debug-macro.S to include/debug/ ARM: exynos: prepare for sparse IRQ ARM: exynos: introduce EXYNOS_ATAGS symbol ARM: tegra: build assembly files with -march=armv7-a ARM: Push selects for TWD/SCU into machine entries ARM: ux500: build hotplug.o for ARMv7-a ARM: ux500: move to multiplatform ARM: ux500: make remaining headers local ARM: ux500: make irqs.h local to platform ARM: ux500: get rid of <mach/[hardware|db8500-regs].h> ...
Diffstat (limited to 'drivers/mfd/db8500-prcmu.c')
-rw-r--r--drivers/mfd/db8500-prcmu.c316
1 files changed, 152 insertions, 164 deletions
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 21f261bf9e95..21434beb420a 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -26,7 +26,6 @@
26#include <linux/fs.h> 26#include <linux/fs.h>
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/uaccess.h> 28#include <linux/uaccess.h>
29#include <linux/irqchip/arm-gic.h>
30#include <linux/mfd/core.h> 29#include <linux/mfd/core.h>
31#include <linux/mfd/dbx500-prcmu.h> 30#include <linux/mfd/dbx500-prcmu.h>
32#include <linux/mfd/abx500/ab8500.h> 31#include <linux/mfd/abx500/ab8500.h>
@@ -34,9 +33,7 @@
34#include <linux/regulator/machine.h> 33#include <linux/regulator/machine.h>
35#include <linux/cpufreq.h> 34#include <linux/cpufreq.h>
36#include <linux/platform_data/ux500_wdt.h> 35#include <linux/platform_data/ux500_wdt.h>
37#include <mach/hardware.h> 36#include <linux/platform_data/db8500_thermal.h>
38#include <mach/irqs.h>
39#include <mach/db8500-regs.h>
40#include "dbx500-prcmu-regs.h" 37#include "dbx500-prcmu-regs.h"
41 38
42/* Index of different voltages to be used when accessing AVSData */ 39/* Index of different voltages to be used when accessing AVSData */
@@ -276,8 +273,34 @@ static struct irq_domain *db8500_irq_domain;
276 * the bits in the bit field are not. (The bits also have a tendency to move 273 * the bits in the bit field are not. (The bits also have a tendency to move
277 * around, to further complicate matters.) 274 * around, to further complicate matters.)
278 */ 275 */
279#define IRQ_INDEX(_name) ((IRQ_PRCMU_##_name) - IRQ_PRCMU_BASE) 276#define IRQ_INDEX(_name) ((IRQ_PRCMU_##_name))
280#define IRQ_ENTRY(_name)[IRQ_INDEX(_name)] = (WAKEUP_BIT_##_name) 277#define IRQ_ENTRY(_name)[IRQ_INDEX(_name)] = (WAKEUP_BIT_##_name)
278
279#define IRQ_PRCMU_RTC 0
280#define IRQ_PRCMU_RTT0 1
281#define IRQ_PRCMU_RTT1 2
282#define IRQ_PRCMU_HSI0 3
283#define IRQ_PRCMU_HSI1 4
284#define IRQ_PRCMU_CA_WAKE 5
285#define IRQ_PRCMU_USB 6
286#define IRQ_PRCMU_ABB 7
287#define IRQ_PRCMU_ABB_FIFO 8
288#define IRQ_PRCMU_ARM 9
289#define IRQ_PRCMU_MODEM_SW_RESET_REQ 10
290#define IRQ_PRCMU_GPIO0 11
291#define IRQ_PRCMU_GPIO1 12
292#define IRQ_PRCMU_GPIO2 13
293#define IRQ_PRCMU_GPIO3 14
294#define IRQ_PRCMU_GPIO4 15
295#define IRQ_PRCMU_GPIO5 16
296#define IRQ_PRCMU_GPIO6 17
297#define IRQ_PRCMU_GPIO7 18
298#define IRQ_PRCMU_GPIO8 19
299#define IRQ_PRCMU_CA_SLEEP 20
300#define IRQ_PRCMU_HOTMON_LOW 21
301#define IRQ_PRCMU_HOTMON_HIGH 22
302#define NUM_PRCMU_WAKEUPS 23
303
281static u32 prcmu_irq_bit[NUM_PRCMU_WAKEUPS] = { 304static u32 prcmu_irq_bit[NUM_PRCMU_WAKEUPS] = {
282 IRQ_ENTRY(RTC), 305 IRQ_ENTRY(RTC),
283 IRQ_ENTRY(RTT0), 306 IRQ_ENTRY(RTT0),
@@ -422,9 +445,10 @@ static DEFINE_SPINLOCK(clkout_lock);
422 445
423/* Global var to runtime determine TCDM base for v2 or v1 */ 446/* Global var to runtime determine TCDM base for v2 or v1 */
424static __iomem void *tcdm_base; 447static __iomem void *tcdm_base;
448static __iomem void *prcmu_base;
425 449
426struct clk_mgt { 450struct clk_mgt {
427 void __iomem *reg; 451 u32 offset;
428 u32 pllsw; 452 u32 pllsw;
429 int branch; 453 int branch;
430 bool clk38div; 454 bool clk38div;
@@ -599,9 +623,9 @@ int db8500_prcmu_set_display_clocks(void)
599 while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) 623 while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
600 cpu_relax(); 624 cpu_relax();
601 625
602 writel(PRCMU_DSI_CLOCK_SETTING, PRCM_HDMICLK_MGT); 626 writel(PRCMU_DSI_CLOCK_SETTING, prcmu_base + PRCM_HDMICLK_MGT);
603 writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT); 627 writel(PRCMU_DSI_LP_CLOCK_SETTING, prcmu_base + PRCM_TVCLK_MGT);
604 writel(PRCMU_DPI_CLOCK_SETTING, PRCM_LCDCLK_MGT); 628 writel(PRCMU_DPI_CLOCK_SETTING, prcmu_base + PRCM_LCDCLK_MGT);
605 629
606 /* Release the HW semaphore. */ 630 /* Release the HW semaphore. */
607 writel(0, PRCM_SEM); 631 writel(0, PRCM_SEM);
@@ -613,7 +637,7 @@ int db8500_prcmu_set_display_clocks(void)
613 637
614u32 db8500_prcmu_read(unsigned int reg) 638u32 db8500_prcmu_read(unsigned int reg)
615{ 639{
616 return readl(_PRCMU_BASE + reg); 640 return readl(prcmu_base + reg);
617} 641}
618 642
619void db8500_prcmu_write(unsigned int reg, u32 value) 643void db8500_prcmu_write(unsigned int reg, u32 value)
@@ -621,7 +645,7 @@ void db8500_prcmu_write(unsigned int reg, u32 value)
621 unsigned long flags; 645 unsigned long flags;
622 646
623 spin_lock_irqsave(&prcmu_lock, flags); 647 spin_lock_irqsave(&prcmu_lock, flags);
624 writel(value, (_PRCMU_BASE + reg)); 648 writel(value, (prcmu_base + reg));
625 spin_unlock_irqrestore(&prcmu_lock, flags); 649 spin_unlock_irqrestore(&prcmu_lock, flags);
626} 650}
627 651
@@ -631,9 +655,9 @@ void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
631 unsigned long flags; 655 unsigned long flags;
632 656
633 spin_lock_irqsave(&prcmu_lock, flags); 657 spin_lock_irqsave(&prcmu_lock, flags);
634 val = readl(_PRCMU_BASE + reg); 658 val = readl(prcmu_base + reg);
635 val = ((val & ~mask) | (value & mask)); 659 val = ((val & ~mask) | (value & mask));
636 writel(val, (_PRCMU_BASE + reg)); 660 writel(val, (prcmu_base + reg));
637 spin_unlock_irqrestore(&prcmu_lock, flags); 661 spin_unlock_irqrestore(&prcmu_lock, flags);
638} 662}
639 663
@@ -793,119 +817,6 @@ u8 db8500_prcmu_get_power_state_result(void)
793 return readb(tcdm_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS); 817 return readb(tcdm_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS);
794} 818}
795 819
796/* This function decouple the gic from the prcmu */
797int db8500_prcmu_gic_decouple(void)
798{
799 u32 val = readl(PRCM_A9_MASK_REQ);
800
801 /* Set bit 0 register value to 1 */
802 writel(val | PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ,
803 PRCM_A9_MASK_REQ);
804
805 /* Make sure the register is updated */
806 readl(PRCM_A9_MASK_REQ);
807
808 /* Wait a few cycles for the gic mask completion */
809 udelay(1);
810
811 return 0;
812}
813
814/* This function recouple the gic with the prcmu */
815int db8500_prcmu_gic_recouple(void)
816{
817 u32 val = readl(PRCM_A9_MASK_REQ);
818
819 /* Set bit 0 register value to 0 */
820 writel(val & ~PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, PRCM_A9_MASK_REQ);
821
822 return 0;
823}
824
825#define PRCMU_GIC_NUMBER_REGS 5
826
827/*
828 * This function checks if there are pending irq on the gic. It only
829 * makes sense if the gic has been decoupled before with the
830 * db8500_prcmu_gic_decouple function. Disabling an interrupt only
831 * disables the forwarding of the interrupt to any CPU interface. It
832 * does not prevent the interrupt from changing state, for example
833 * becoming pending, or active and pending if it is already
834 * active. Hence, we have to check the interrupt is pending *and* is
835 * active.
836 */
837bool db8500_prcmu_gic_pending_irq(void)
838{
839 u32 pr; /* Pending register */
840 u32 er; /* Enable register */
841 void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE);
842 int i;
843
844 /* 5 registers. STI & PPI not skipped */
845 for (i = 0; i < PRCMU_GIC_NUMBER_REGS; i++) {
846
847 pr = readl_relaxed(dist_base + GIC_DIST_PENDING_SET + i * 4);
848 er = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
849
850 if (pr & er)
851 return true; /* There is a pending interrupt */
852 }
853
854 return false;
855}
856
857/*
858 * This function checks if there are pending interrupt on the
859 * prcmu which has been delegated to monitor the irqs with the
860 * db8500_prcmu_copy_gic_settings function.
861 */
862bool db8500_prcmu_pending_irq(void)
863{
864 u32 it, im;
865 int i;
866
867 for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) {
868 it = readl(PRCM_ARMITVAL31TO0 + i * 4);
869 im = readl(PRCM_ARMITMSK31TO0 + i * 4);
870 if (it & im)
871 return true; /* There is a pending interrupt */
872 }
873
874 return false;
875}
876
877/*
878 * This function checks if the specified cpu is in in WFI. It's usage
879 * makes sense only if the gic is decoupled with the db8500_prcmu_gic_decouple
880 * function. Of course passing smp_processor_id() to this function will
881 * always return false...
882 */
883bool db8500_prcmu_is_cpu_in_wfi(int cpu)
884{
885 return readl(PRCM_ARM_WFI_STANDBY) & cpu ? PRCM_ARM_WFI_STANDBY_WFI1 :
886 PRCM_ARM_WFI_STANDBY_WFI0;
887}
888
889/*
890 * This function copies the gic SPI settings to the prcmu in order to
891 * monitor them and abort/finish the retention/off sequence or state.
892 */
893int db8500_prcmu_copy_gic_settings(void)
894{
895 u32 er; /* Enable register */
896 void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE);
897 int i;
898
899 /* We skip the STI and PPI */
900 for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) {
901 er = readl_relaxed(dist_base +
902 GIC_DIST_ENABLE_SET + (i + 1) * 4);
903 writel(er, PRCM_ARMITMSK31TO0 + i * 4);
904 }
905
906 return 0;
907}
908
909/* This function should only be called while mb0_transfer.lock is held. */ 820/* This function should only be called while mb0_transfer.lock is held. */
910static void config_wakeups(void) 821static void config_wakeups(void)
911{ 822{
@@ -1059,7 +970,7 @@ int db8500_prcmu_set_ddr_opp(u8 opp)
1059/* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */ 970/* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */
1060static void request_even_slower_clocks(bool enable) 971static void request_even_slower_clocks(bool enable)
1061{ 972{
1062 void __iomem *clock_reg[] = { 973 u32 clock_reg[] = {
1063 PRCM_ACLK_MGT, 974 PRCM_ACLK_MGT,
1064 PRCM_DMACLK_MGT 975 PRCM_DMACLK_MGT
1065 }; 976 };
@@ -1076,7 +987,7 @@ static void request_even_slower_clocks(bool enable)
1076 u32 val; 987 u32 val;
1077 u32 div; 988 u32 div;
1078 989
1079 val = readl(clock_reg[i]); 990 val = readl(prcmu_base + clock_reg[i]);
1080 div = (val & PRCM_CLK_MGT_CLKPLLDIV_MASK); 991 div = (val & PRCM_CLK_MGT_CLKPLLDIV_MASK);
1081 if (enable) { 992 if (enable) {
1082 if ((div <= 1) || (div > 15)) { 993 if ((div <= 1) || (div > 15)) {
@@ -1092,7 +1003,7 @@ static void request_even_slower_clocks(bool enable)
1092 } 1003 }
1093 val = ((val & ~PRCM_CLK_MGT_CLKPLLDIV_MASK) | 1004 val = ((val & ~PRCM_CLK_MGT_CLKPLLDIV_MASK) |
1094 (div & PRCM_CLK_MGT_CLKPLLDIV_MASK)); 1005 (div & PRCM_CLK_MGT_CLKPLLDIV_MASK));
1095 writel(val, clock_reg[i]); 1006 writel(val, prcmu_base + clock_reg[i]);
1096 } 1007 }
1097 1008
1098unlock_and_return: 1009unlock_and_return:
@@ -1446,14 +1357,14 @@ static int request_clock(u8 clock, bool enable)
1446 while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) 1357 while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
1447 cpu_relax(); 1358 cpu_relax();
1448 1359
1449 val = readl(clk_mgt[clock].reg); 1360 val = readl(prcmu_base + clk_mgt[clock].offset);
1450 if (enable) { 1361 if (enable) {
1451 val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw); 1362 val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw);
1452 } else { 1363 } else {
1453 clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); 1364 clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
1454 val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK); 1365 val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK);
1455 } 1366 }
1456 writel(val, clk_mgt[clock].reg); 1367 writel(val, prcmu_base + clk_mgt[clock].offset);
1457 1368
1458 /* Release the HW semaphore. */ 1369 /* Release the HW semaphore. */
1459 writel(0, PRCM_SEM); 1370 writel(0, PRCM_SEM);
@@ -1629,7 +1540,7 @@ static unsigned long clock_rate(u8 clock)
1629 u32 pllsw; 1540 u32 pllsw;
1630 unsigned long rate = ROOT_CLOCK_RATE; 1541 unsigned long rate = ROOT_CLOCK_RATE;
1631 1542
1632 val = readl(clk_mgt[clock].reg); 1543 val = readl(prcmu_base + clk_mgt[clock].offset);
1633 1544
1634 if (val & PRCM_CLK_MGT_CLK38) { 1545 if (val & PRCM_CLK_MGT_CLK38) {
1635 if (clk_mgt[clock].clk38div && (val & PRCM_CLK_MGT_CLK38DIV)) 1546 if (clk_mgt[clock].clk38div && (val & PRCM_CLK_MGT_CLK38DIV))
@@ -1785,7 +1696,7 @@ static long round_clock_rate(u8 clock, unsigned long rate)
1785 unsigned long src_rate; 1696 unsigned long src_rate;
1786 long rounded_rate; 1697 long rounded_rate;
1787 1698
1788 val = readl(clk_mgt[clock].reg); 1699 val = readl(prcmu_base + clk_mgt[clock].offset);
1789 src_rate = clock_source_rate((val | clk_mgt[clock].pllsw), 1700 src_rate = clock_source_rate((val | clk_mgt[clock].pllsw),
1790 clk_mgt[clock].branch); 1701 clk_mgt[clock].branch);
1791 div = clock_divider(src_rate, rate); 1702 div = clock_divider(src_rate, rate);
@@ -1933,7 +1844,7 @@ static void set_clock_rate(u8 clock, unsigned long rate)
1933 while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) 1844 while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
1934 cpu_relax(); 1845 cpu_relax();
1935 1846
1936 val = readl(clk_mgt[clock].reg); 1847 val = readl(prcmu_base + clk_mgt[clock].offset);
1937 src_rate = clock_source_rate((val | clk_mgt[clock].pllsw), 1848 src_rate = clock_source_rate((val | clk_mgt[clock].pllsw),
1938 clk_mgt[clock].branch); 1849 clk_mgt[clock].branch);
1939 div = clock_divider(src_rate, rate); 1850 div = clock_divider(src_rate, rate);
@@ -1961,7 +1872,7 @@ static void set_clock_rate(u8 clock, unsigned long rate)
1961 val &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK; 1872 val &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK;
1962 val |= min(div, (u32)31); 1873 val |= min(div, (u32)31);
1963 } 1874 }
1964 writel(val, clk_mgt[clock].reg); 1875 writel(val, prcmu_base + clk_mgt[clock].offset);
1965 1876
1966 /* Release the HW semaphore. */ 1877 /* Release the HW semaphore. */
1967 writel(0, PRCM_SEM); 1878 writel(0, PRCM_SEM);
@@ -2764,14 +2675,13 @@ static struct irq_domain_ops db8500_irq_ops = {
2764 .xlate = irq_domain_xlate_twocell, 2675 .xlate = irq_domain_xlate_twocell,
2765}; 2676};
2766 2677
2767static int db8500_irq_init(struct device_node *np) 2678static int db8500_irq_init(struct device_node *np, int irq_base)
2768{ 2679{
2769 int irq_base = 0;
2770 int i; 2680 int i;
2771 2681
2772 /* In the device tree case, just take some IRQs */ 2682 /* In the device tree case, just take some IRQs */
2773 if (!np) 2683 if (np)
2774 irq_base = IRQ_PRCMU_BASE; 2684 irq_base = 0;
2775 2685
2776 db8500_irq_domain = irq_domain_add_simple( 2686 db8500_irq_domain = irq_domain_add_simple(
2777 np, NUM_PRCMU_WAKEUPS, irq_base, 2687 np, NUM_PRCMU_WAKEUPS, irq_base,
@@ -2825,8 +2735,19 @@ static void dbx500_fw_version_init(struct platform_device *pdev,
2825 } 2735 }
2826} 2736}
2827 2737
2828void __init db8500_prcmu_early_init(void) 2738void __init db8500_prcmu_early_init(u32 phy_base, u32 size)
2829{ 2739{
2740 /*
2741 * This is a temporary remap to bring up the clocks. It is
2742 * subsequently replaces with a real remap. After the merge of
2743 * the mailbox subsystem all of this early code goes away, and the
2744 * clock driver can probe independently. An early initcall will
2745 * still be needed, but it can be diverted into drivers/clk/ux500.
2746 */
2747 prcmu_base = ioremap(phy_base, size);
2748 if (!prcmu_base)
2749 pr_err("%s: ioremap() of prcmu registers failed!\n", __func__);
2750
2830 spin_lock_init(&mb0_transfer.lock); 2751 spin_lock_init(&mb0_transfer.lock);
2831 spin_lock_init(&mb0_transfer.dbb_irqs_lock); 2752 spin_lock_init(&mb0_transfer.dbb_irqs_lock);
2832 mutex_init(&mb0_transfer.ac_wake_lock); 2753 mutex_init(&mb0_transfer.ac_wake_lock);
@@ -3092,18 +3013,57 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
3092 }, 3013 },
3093}; 3014};
3094 3015
3095static struct resource ab8500_resources[] = {
3096 [0] = {
3097 .start = IRQ_DB8500_AB8500,
3098 .end = IRQ_DB8500_AB8500,
3099 .flags = IORESOURCE_IRQ
3100 }
3101};
3102
3103static struct ux500_wdt_data db8500_wdt_pdata = { 3016static struct ux500_wdt_data db8500_wdt_pdata = {
3104 .timeout = 600, /* 10 minutes */ 3017 .timeout = 600, /* 10 minutes */
3105 .has_28_bits_resolution = true, 3018 .has_28_bits_resolution = true,
3106}; 3019};
3020/*
3021 * Thermal Sensor
3022 */
3023
3024static struct resource db8500_thsens_resources[] = {
3025 {
3026 .name = "IRQ_HOTMON_LOW",
3027 .start = IRQ_PRCMU_HOTMON_LOW,
3028 .end = IRQ_PRCMU_HOTMON_LOW,
3029 .flags = IORESOURCE_IRQ,
3030 },
3031 {
3032 .name = "IRQ_HOTMON_HIGH",
3033 .start = IRQ_PRCMU_HOTMON_HIGH,
3034 .end = IRQ_PRCMU_HOTMON_HIGH,
3035 .flags = IORESOURCE_IRQ,
3036 },
3037};
3038
3039static struct db8500_thsens_platform_data db8500_thsens_data = {
3040 .trip_points[0] = {
3041 .temp = 70000,
3042 .type = THERMAL_TRIP_ACTIVE,
3043 .cdev_name = {
3044 [0] = "thermal-cpufreq-0",
3045 },
3046 },
3047 .trip_points[1] = {
3048 .temp = 75000,
3049 .type = THERMAL_TRIP_ACTIVE,
3050 .cdev_name = {
3051 [0] = "thermal-cpufreq-0",
3052 },
3053 },
3054 .trip_points[2] = {
3055 .temp = 80000,
3056 .type = THERMAL_TRIP_ACTIVE,
3057 .cdev_name = {
3058 [0] = "thermal-cpufreq-0",
3059 },
3060 },
3061 .trip_points[3] = {
3062 .temp = 85000,
3063 .type = THERMAL_TRIP_CRITICAL,
3064 },
3065 .num_trips = 4,
3066};
3107 3067
3108static struct mfd_cell db8500_prcmu_devs[] = { 3068static struct mfd_cell db8500_prcmu_devs[] = {
3109 { 3069 {
@@ -3125,11 +3085,10 @@ static struct mfd_cell db8500_prcmu_devs[] = {
3125 .id = -1, 3085 .id = -1,
3126 }, 3086 },
3127 { 3087 {
3128 .name = "ab8500-core", 3088 .name = "db8500-thermal",
3129 .of_compatible = "stericsson,ab8500", 3089 .num_resources = ARRAY_SIZE(db8500_thsens_resources),
3130 .num_resources = ARRAY_SIZE(ab8500_resources), 3090 .resources = db8500_thsens_resources,
3131 .resources = ab8500_resources, 3091 .platform_data = &db8500_thsens_data,
3132 .id = AB8500_VERSION_AB8500,
3133 }, 3092 },
3134}; 3093};
3135 3094
@@ -3141,6 +3100,24 @@ static void db8500_prcmu_update_cpufreq(void)
3141 } 3100 }
3142} 3101}
3143 3102
3103static int db8500_prcmu_register_ab8500(struct device *parent,
3104 struct ab8500_platform_data *pdata,
3105 int irq)
3106{
3107 struct resource ab8500_resource = DEFINE_RES_IRQ(irq);
3108 struct mfd_cell ab8500_cell = {
3109 .name = "ab8500-core",
3110 .of_compatible = "stericsson,ab8500",
3111 .id = AB8500_VERSION_AB8500,
3112 .platform_data = pdata,
3113 .pdata_size = sizeof(struct ab8500_platform_data),
3114 .resources = &ab8500_resource,
3115 .num_resources = 1,
3116 };
3117
3118 return mfd_add_devices(parent, 0, &ab8500_cell, 1, NULL, 0, NULL);
3119}
3120
3144/** 3121/**
3145 * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic 3122 * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
3146 * 3123 *
@@ -3149,11 +3126,21 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
3149{ 3126{
3150 struct device_node *np = pdev->dev.of_node; 3127 struct device_node *np = pdev->dev.of_node;
3151 struct prcmu_pdata *pdata = dev_get_platdata(&pdev->dev); 3128 struct prcmu_pdata *pdata = dev_get_platdata(&pdev->dev);
3152 int irq = 0, err = 0, i; 3129 int irq = 0, err = 0;
3153 struct resource *res; 3130 struct resource *res;
3154 3131
3132 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu");
3133 if (!res) {
3134 dev_err(&pdev->dev, "no prcmu memory region provided\n");
3135 return -ENOENT;
3136 }
3137 prcmu_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
3138 if (!prcmu_base) {
3139 dev_err(&pdev->dev,
3140 "failed to ioremap prcmu register memory\n");
3141 return -ENOENT;
3142 }
3155 init_prcm_registers(); 3143 init_prcm_registers();
3156
3157 dbx500_fw_version_init(pdev, pdata->version_offset); 3144 dbx500_fw_version_init(pdev, pdata->version_offset);
3158 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm"); 3145 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
3159 if (!res) { 3146 if (!res) {
@@ -3180,26 +3167,27 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
3180 goto no_irq_return; 3167 goto no_irq_return;
3181 } 3168 }
3182 3169
3183 db8500_irq_init(np); 3170 db8500_irq_init(np, pdata->irq_base);
3184
3185 for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) {
3186 if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) {
3187 db8500_prcmu_devs[i].platform_data = pdata->ab_platdata;
3188 db8500_prcmu_devs[i].pdata_size = sizeof(struct ab8500_platform_data);
3189 }
3190 }
3191 3171
3192 prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); 3172 prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
3193 3173
3194 db8500_prcmu_update_cpufreq(); 3174 db8500_prcmu_update_cpufreq();
3195 3175
3196 err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, 3176 err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs,
3197 ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL); 3177 ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, db8500_irq_domain);
3198 if (err) { 3178 if (err) {
3199 pr_err("prcmu: Failed to add subdevices\n"); 3179 pr_err("prcmu: Failed to add subdevices\n");
3200 return err; 3180 return err;
3201 } 3181 }
3202 3182
3183 err = db8500_prcmu_register_ab8500(&pdev->dev, pdata->ab_platdata,
3184 pdata->ab_irq);
3185 if (err) {
3186 mfd_remove_devices(&pdev->dev);
3187 pr_err("prcmu: Failed to add ab8500 subdevice\n");
3188 goto no_irq_return;
3189 }
3190
3203 pr_info("DB8500 PRCMU initialized\n"); 3191 pr_info("DB8500 PRCMU initialized\n");
3204 3192
3205no_irq_return: 3193no_irq_return: