diff options
Diffstat (limited to 'drivers/mfd/db8500-prcmu.c')
-rw-r--r-- | drivers/mfd/db8500-prcmu.c | 316 |
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 | |||
281 | static u32 prcmu_irq_bit[NUM_PRCMU_WAKEUPS] = { | 304 | static 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 */ |
424 | static __iomem void *tcdm_base; | 447 | static __iomem void *tcdm_base; |
448 | static __iomem void *prcmu_base; | ||
425 | 449 | ||
426 | struct clk_mgt { | 450 | struct 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 | ||
614 | u32 db8500_prcmu_read(unsigned int reg) | 638 | u32 db8500_prcmu_read(unsigned int reg) |
615 | { | 639 | { |
616 | return readl(_PRCMU_BASE + reg); | 640 | return readl(prcmu_base + reg); |
617 | } | 641 | } |
618 | 642 | ||
619 | void db8500_prcmu_write(unsigned int reg, u32 value) | 643 | void 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 */ | ||
797 | int 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 */ | ||
815 | int 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 | */ | ||
837 | bool 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 | */ | ||
862 | bool 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 | */ | ||
883 | bool 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 | */ | ||
893 | int 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. */ |
910 | static void config_wakeups(void) | 821 | static 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. */ |
1060 | static void request_even_slower_clocks(bool enable) | 971 | static 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 | ||
1098 | unlock_and_return: | 1009 | unlock_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 | ||
2767 | static int db8500_irq_init(struct device_node *np) | 2678 | static 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 | ||
2828 | void __init db8500_prcmu_early_init(void) | 2738 | void __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 | ||
3095 | static struct resource ab8500_resources[] = { | ||
3096 | [0] = { | ||
3097 | .start = IRQ_DB8500_AB8500, | ||
3098 | .end = IRQ_DB8500_AB8500, | ||
3099 | .flags = IORESOURCE_IRQ | ||
3100 | } | ||
3101 | }; | ||
3102 | |||
3103 | static struct ux500_wdt_data db8500_wdt_pdata = { | 3016 | static 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 | |||
3024 | static 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 | |||
3039 | static 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 | ||
3108 | static struct mfd_cell db8500_prcmu_devs[] = { | 3068 | static 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 | ||
3103 | static 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 | ||
3205 | no_irq_return: | 3193 | no_irq_return: |