.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
| 3 | + * DB8500 PRCM Unit driver |
---|
| 4 | + * |
---|
2 | 5 | * Copyright (C) STMicroelectronics 2009 |
---|
3 | 6 | * Copyright (C) ST-Ericsson SA 2010 |
---|
4 | 7 | * |
---|
5 | | - * License Terms: GNU General Public License v2 |
---|
6 | 8 | * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> |
---|
7 | 9 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> |
---|
8 | 10 | * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> |
---|
9 | 11 | * |
---|
10 | 12 | * U8500 PRCM Unit interface driver |
---|
11 | | - * |
---|
12 | 13 | */ |
---|
13 | | -#include <linux/module.h> |
---|
| 14 | +#include <linux/init.h> |
---|
| 15 | +#include <linux/export.h> |
---|
14 | 16 | #include <linux/kernel.h> |
---|
15 | 17 | #include <linux/delay.h> |
---|
16 | 18 | #include <linux/errno.h> |
---|
.. | .. |
---|
25 | 27 | #include <linux/bitops.h> |
---|
26 | 28 | #include <linux/fs.h> |
---|
27 | 29 | #include <linux/of.h> |
---|
| 30 | +#include <linux/of_address.h> |
---|
28 | 31 | #include <linux/of_irq.h> |
---|
29 | 32 | #include <linux/platform_device.h> |
---|
30 | 33 | #include <linux/uaccess.h> |
---|
.. | .. |
---|
34 | 37 | #include <linux/regulator/db8500-prcmu.h> |
---|
35 | 38 | #include <linux/regulator/machine.h> |
---|
36 | 39 | #include <linux/platform_data/ux500_wdt.h> |
---|
37 | | -#include <linux/platform_data/db8500_thermal.h> |
---|
38 | 40 | #include "dbx500-prcmu-regs.h" |
---|
39 | 41 | |
---|
40 | 42 | /* Index of different voltages to be used when accessing AVSData */ |
---|
.. | .. |
---|
540 | 542 | } |
---|
541 | 543 | }; |
---|
542 | 544 | |
---|
543 | | - |
---|
544 | | -/* |
---|
545 | | -* Used by MCDE to setup all necessary PRCMU registers |
---|
546 | | -*/ |
---|
547 | | -#define PRCMU_RESET_DSIPLL 0x00004000 |
---|
548 | | -#define PRCMU_UNCLAMP_DSIPLL 0x00400800 |
---|
549 | | - |
---|
550 | | -#define PRCMU_CLK_PLL_DIV_SHIFT 0 |
---|
551 | | -#define PRCMU_CLK_PLL_SW_SHIFT 5 |
---|
552 | | -#define PRCMU_CLK_38 (1 << 9) |
---|
553 | | -#define PRCMU_CLK_38_SRC (1 << 10) |
---|
554 | | -#define PRCMU_CLK_38_DIV (1 << 11) |
---|
555 | | - |
---|
556 | | -/* PLLDIV=12, PLLSW=4 (PLLDDR) */ |
---|
557 | | -#define PRCMU_DSI_CLOCK_SETTING 0x0000008C |
---|
558 | | - |
---|
559 | | -/* DPI 50000000 Hz */ |
---|
560 | | -#define PRCMU_DPI_CLOCK_SETTING ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \ |
---|
561 | | - (16 << PRCMU_CLK_PLL_DIV_SHIFT)) |
---|
562 | | -#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000E00 |
---|
563 | | - |
---|
564 | | -/* D=101, N=1, R=4, SELDIV2=0 */ |
---|
565 | | -#define PRCMU_PLLDSI_FREQ_SETTING 0x00040165 |
---|
566 | | - |
---|
567 | | -#define PRCMU_ENABLE_PLLDSI 0x00000001 |
---|
568 | | -#define PRCMU_DISABLE_PLLDSI 0x00000000 |
---|
569 | | -#define PRCMU_RELEASE_RESET_DSS 0x0000400C |
---|
570 | | -#define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000202 |
---|
571 | | -/* ESC clk, div0=1, div1=1, div2=3 */ |
---|
572 | | -#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x07030101 |
---|
573 | | -#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00030101 |
---|
574 | | -#define PRCMU_DSI_RESET_SW 0x00000007 |
---|
575 | | - |
---|
576 | | -#define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 |
---|
577 | | - |
---|
578 | | -int db8500_prcmu_enable_dsipll(void) |
---|
579 | | -{ |
---|
580 | | - int i; |
---|
581 | | - |
---|
582 | | - /* Clear DSIPLL_RESETN */ |
---|
583 | | - writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR); |
---|
584 | | - /* Unclamp DSIPLL in/out */ |
---|
585 | | - writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR); |
---|
586 | | - |
---|
587 | | - /* Set DSI PLL FREQ */ |
---|
588 | | - writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ); |
---|
589 | | - writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL); |
---|
590 | | - /* Enable Escape clocks */ |
---|
591 | | - writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); |
---|
592 | | - |
---|
593 | | - /* Start DSI PLL */ |
---|
594 | | - writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE); |
---|
595 | | - /* Reset DSI PLL */ |
---|
596 | | - writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET); |
---|
597 | | - for (i = 0; i < 10; i++) { |
---|
598 | | - if ((readl(PRCM_PLLDSI_LOCKP) & PRCMU_PLLDSI_LOCKP_LOCKED) |
---|
599 | | - == PRCMU_PLLDSI_LOCKP_LOCKED) |
---|
600 | | - break; |
---|
601 | | - udelay(100); |
---|
602 | | - } |
---|
603 | | - /* Set DSIPLL_RESETN */ |
---|
604 | | - writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_SET); |
---|
605 | | - return 0; |
---|
606 | | -} |
---|
607 | | - |
---|
608 | | -int db8500_prcmu_disable_dsipll(void) |
---|
609 | | -{ |
---|
610 | | - /* Disable dsi pll */ |
---|
611 | | - writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE); |
---|
612 | | - /* Disable escapeclock */ |
---|
613 | | - writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); |
---|
614 | | - return 0; |
---|
615 | | -} |
---|
616 | | - |
---|
617 | | -int db8500_prcmu_set_display_clocks(void) |
---|
618 | | -{ |
---|
619 | | - unsigned long flags; |
---|
620 | | - |
---|
621 | | - spin_lock_irqsave(&clk_mgt_lock, flags); |
---|
622 | | - |
---|
623 | | - /* Grab the HW semaphore. */ |
---|
624 | | - while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) |
---|
625 | | - cpu_relax(); |
---|
626 | | - |
---|
627 | | - writel(PRCMU_DSI_CLOCK_SETTING, prcmu_base + PRCM_HDMICLK_MGT); |
---|
628 | | - writel(PRCMU_DSI_LP_CLOCK_SETTING, prcmu_base + PRCM_TVCLK_MGT); |
---|
629 | | - writel(PRCMU_DPI_CLOCK_SETTING, prcmu_base + PRCM_LCDCLK_MGT); |
---|
630 | | - |
---|
631 | | - /* Release the HW semaphore. */ |
---|
632 | | - writel(0, PRCM_SEM); |
---|
633 | | - |
---|
634 | | - spin_unlock_irqrestore(&clk_mgt_lock, flags); |
---|
635 | | - |
---|
636 | | - return 0; |
---|
637 | | -} |
---|
638 | | - |
---|
639 | 545 | u32 db8500_prcmu_read(unsigned int reg) |
---|
640 | 546 | { |
---|
641 | 547 | return readl(prcmu_base + reg); |
---|
.. | .. |
---|
665 | 571 | struct prcmu_fw_version *prcmu_get_fw_version(void) |
---|
666 | 572 | { |
---|
667 | 573 | return fw_info.valid ? &fw_info.version : NULL; |
---|
| 574 | +} |
---|
| 575 | + |
---|
| 576 | +static bool prcmu_is_ulppll_disabled(void) |
---|
| 577 | +{ |
---|
| 578 | + struct prcmu_fw_version *ver; |
---|
| 579 | + |
---|
| 580 | + ver = prcmu_get_fw_version(); |
---|
| 581 | + return ver && ver->project == PRCMU_FW_PROJECT_U8420_SYSCLK; |
---|
668 | 582 | } |
---|
669 | 583 | |
---|
670 | 584 | bool prcmu_has_arm_maxopp(void) |
---|
.. | .. |
---|
1307 | 1221 | |
---|
1308 | 1222 | static int request_timclk(bool enable) |
---|
1309 | 1223 | { |
---|
1310 | | - u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK); |
---|
| 1224 | + u32 val; |
---|
| 1225 | + |
---|
| 1226 | + /* |
---|
| 1227 | + * On the U8420_CLKSEL firmware, the ULP (Ultra Low Power) |
---|
| 1228 | + * PLL is disabled so we cannot use doze mode, this will |
---|
| 1229 | + * stop the clock on this firmware. |
---|
| 1230 | + */ |
---|
| 1231 | + if (prcmu_is_ulppll_disabled()) |
---|
| 1232 | + val = 0; |
---|
| 1233 | + else |
---|
| 1234 | + val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK); |
---|
1311 | 1235 | |
---|
1312 | 1236 | if (!enable) |
---|
1313 | | - val |= PRCM_TCR_STOP_TIMERS; |
---|
| 1237 | + val |= PRCM_TCR_STOP_TIMERS | |
---|
| 1238 | + PRCM_TCR_DOZE_MODE | |
---|
| 1239 | + PRCM_TCR_TENSEL_MASK; |
---|
| 1240 | + |
---|
1314 | 1241 | writel(val, PRCM_TCR); |
---|
1315 | 1242 | |
---|
1316 | 1243 | return 0; |
---|
.. | .. |
---|
1588 | 1515 | switch (divsel) { |
---|
1589 | 1516 | case PRCM_DSI_PLLOUT_SEL_PHI_4: |
---|
1590 | 1517 | div *= 2; |
---|
| 1518 | + fallthrough; |
---|
1591 | 1519 | case PRCM_DSI_PLLOUT_SEL_PHI_2: |
---|
1592 | 1520 | div *= 2; |
---|
| 1521 | + fallthrough; |
---|
1593 | 1522 | case PRCM_DSI_PLLOUT_SEL_PHI: |
---|
1594 | 1523 | return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK), |
---|
1595 | 1524 | PLL_RAW) / div; |
---|
.. | .. |
---|
1612 | 1541 | if (clock < PRCMU_NUM_REG_CLOCKS) |
---|
1613 | 1542 | return clock_rate(clock); |
---|
1614 | 1543 | else if (clock == PRCMU_TIMCLK) |
---|
1615 | | - return ROOT_CLOCK_RATE / 16; |
---|
| 1544 | + return prcmu_is_ulppll_disabled() ? |
---|
| 1545 | + 32768 : ROOT_CLOCK_RATE / 16; |
---|
1616 | 1546 | else if (clock == PRCMU_SYSCLK) |
---|
1617 | 1547 | return ROOT_CLOCK_RATE; |
---|
1618 | 1548 | else if (clock == PRCMU_PLLSOC0) |
---|
.. | .. |
---|
1691 | 1621 | return rounded_rate; |
---|
1692 | 1622 | } |
---|
1693 | 1623 | |
---|
1694 | | -static const unsigned long armss_freqs[] = { |
---|
1695 | | - 200000000, |
---|
1696 | | - 400000000, |
---|
1697 | | - 800000000, |
---|
| 1624 | +static const unsigned long db8500_armss_freqs[] = { |
---|
| 1625 | + 199680000, |
---|
| 1626 | + 399360000, |
---|
| 1627 | + 798720000, |
---|
1698 | 1628 | 998400000 |
---|
| 1629 | +}; |
---|
| 1630 | + |
---|
| 1631 | +/* The DB8520 has slightly higher ARMSS max frequency */ |
---|
| 1632 | +static const unsigned long db8520_armss_freqs[] = { |
---|
| 1633 | + 199680000, |
---|
| 1634 | + 399360000, |
---|
| 1635 | + 798720000, |
---|
| 1636 | + 1152000000 |
---|
1699 | 1637 | }; |
---|
1700 | 1638 | |
---|
1701 | 1639 | static long round_armss_rate(unsigned long rate) |
---|
1702 | 1640 | { |
---|
1703 | 1641 | unsigned long freq = 0; |
---|
| 1642 | + const unsigned long *freqs; |
---|
| 1643 | + int nfreqs; |
---|
1704 | 1644 | int i; |
---|
1705 | 1645 | |
---|
| 1646 | + if (fw_info.version.project == PRCMU_FW_PROJECT_U8520) { |
---|
| 1647 | + freqs = db8520_armss_freqs; |
---|
| 1648 | + nfreqs = ARRAY_SIZE(db8520_armss_freqs); |
---|
| 1649 | + } else { |
---|
| 1650 | + freqs = db8500_armss_freqs; |
---|
| 1651 | + nfreqs = ARRAY_SIZE(db8500_armss_freqs); |
---|
| 1652 | + } |
---|
| 1653 | + |
---|
1706 | 1654 | /* Find the corresponding arm opp from the cpufreq table. */ |
---|
1707 | | - for (i = 0; i < ARRAY_SIZE(armss_freqs); i++) { |
---|
1708 | | - freq = armss_freqs[i]; |
---|
| 1655 | + for (i = 0; i < nfreqs; i++) { |
---|
| 1656 | + freq = freqs[i]; |
---|
1709 | 1657 | if (rate <= freq) |
---|
1710 | 1658 | break; |
---|
1711 | 1659 | } |
---|
.. | .. |
---|
1850 | 1798 | { |
---|
1851 | 1799 | unsigned long freq; |
---|
1852 | 1800 | u8 opps[] = { ARM_EXTCLK, ARM_50_OPP, ARM_100_OPP, ARM_MAX_OPP }; |
---|
| 1801 | + const unsigned long *freqs; |
---|
| 1802 | + int nfreqs; |
---|
1853 | 1803 | int i; |
---|
1854 | 1804 | |
---|
| 1805 | + if (fw_info.version.project == PRCMU_FW_PROJECT_U8520) { |
---|
| 1806 | + freqs = db8520_armss_freqs; |
---|
| 1807 | + nfreqs = ARRAY_SIZE(db8520_armss_freqs); |
---|
| 1808 | + } else { |
---|
| 1809 | + freqs = db8500_armss_freqs; |
---|
| 1810 | + nfreqs = ARRAY_SIZE(db8500_armss_freqs); |
---|
| 1811 | + } |
---|
| 1812 | + |
---|
1855 | 1813 | /* Find the corresponding arm opp from the cpufreq table. */ |
---|
1856 | | - for (i = 0; i < ARRAY_SIZE(armss_freqs); i++) { |
---|
1857 | | - freq = armss_freqs[i]; |
---|
| 1814 | + for (i = 0; i < nfreqs; i++) { |
---|
| 1815 | + freq = freqs[i]; |
---|
1858 | 1816 | if (rate == freq) |
---|
1859 | 1817 | break; |
---|
1860 | 1818 | } |
---|
.. | .. |
---|
2316 | 2274 | * |
---|
2317 | 2275 | * Saves the reset reason code and then sets the APE_SOFTRST register which |
---|
2318 | 2276 | * fires interrupt to fw |
---|
| 2277 | + * |
---|
| 2278 | + * @reset_code: The reason for system reset |
---|
2319 | 2279 | */ |
---|
2320 | 2280 | void db8500_prcmu_system_reset(u16 reset_code) |
---|
2321 | 2281 | { |
---|
.. | .. |
---|
2613 | 2573 | return "U8520 MBL"; |
---|
2614 | 2574 | case PRCMU_FW_PROJECT_U8420: |
---|
2615 | 2575 | return "U8420"; |
---|
| 2576 | + case PRCMU_FW_PROJECT_U8420_SYSCLK: |
---|
| 2577 | + return "U8420-sysclk"; |
---|
2616 | 2578 | case PRCMU_FW_PROJECT_U9540: |
---|
2617 | 2579 | return "U9540"; |
---|
2618 | 2580 | case PRCMU_FW_PROJECT_A9420: |
---|
.. | .. |
---|
2660 | 2622 | return 0; |
---|
2661 | 2623 | } |
---|
2662 | 2624 | |
---|
2663 | | -static void dbx500_fw_version_init(struct platform_device *pdev, |
---|
2664 | | - u32 version_offset) |
---|
| 2625 | +static void dbx500_fw_version_init(struct device_node *np) |
---|
2665 | 2626 | { |
---|
2666 | | - struct resource *res; |
---|
2667 | 2627 | void __iomem *tcpm_base; |
---|
2668 | 2628 | u32 version; |
---|
2669 | 2629 | |
---|
2670 | | - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
---|
2671 | | - "prcmu-tcpm"); |
---|
2672 | | - if (!res) { |
---|
2673 | | - dev_err(&pdev->dev, |
---|
2674 | | - "Error: no prcmu tcpm memory region provided\n"); |
---|
2675 | | - return; |
---|
2676 | | - } |
---|
2677 | | - tcpm_base = ioremap(res->start, resource_size(res)); |
---|
| 2630 | + tcpm_base = of_iomap(np, 1); |
---|
2678 | 2631 | if (!tcpm_base) { |
---|
2679 | | - dev_err(&pdev->dev, "no prcmu tcpm mem region provided\n"); |
---|
| 2632 | + pr_err("no prcmu tcpm mem region provided\n"); |
---|
2680 | 2633 | return; |
---|
2681 | 2634 | } |
---|
2682 | 2635 | |
---|
2683 | | - version = readl(tcpm_base + version_offset); |
---|
| 2636 | + version = readl(tcpm_base + DB8500_PRCMU_FW_VERSION_OFFSET); |
---|
2684 | 2637 | fw_info.version.project = (version & 0xFF); |
---|
2685 | 2638 | fw_info.version.api_version = (version >> 8) & 0xFF; |
---|
2686 | 2639 | fw_info.version.func_version = (version >> 16) & 0xFF; |
---|
.. | .. |
---|
2698 | 2651 | iounmap(tcpm_base); |
---|
2699 | 2652 | } |
---|
2700 | 2653 | |
---|
2701 | | -void __init db8500_prcmu_early_init(u32 phy_base, u32 size) |
---|
| 2654 | +void __init db8500_prcmu_early_init(void) |
---|
2702 | 2655 | { |
---|
2703 | 2656 | /* |
---|
2704 | 2657 | * This is a temporary remap to bring up the clocks. It is |
---|
.. | .. |
---|
2707 | 2660 | * clock driver can probe independently. An early initcall will |
---|
2708 | 2661 | * still be needed, but it can be diverted into drivers/clk/ux500. |
---|
2709 | 2662 | */ |
---|
2710 | | - prcmu_base = ioremap(phy_base, size); |
---|
2711 | | - if (!prcmu_base) |
---|
| 2663 | + struct device_node *np; |
---|
| 2664 | + |
---|
| 2665 | + np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu"); |
---|
| 2666 | + prcmu_base = of_iomap(np, 0); |
---|
| 2667 | + if (!prcmu_base) { |
---|
| 2668 | + of_node_put(np); |
---|
2712 | 2669 | pr_err("%s: ioremap() of prcmu registers failed!\n", __func__); |
---|
| 2670 | + return; |
---|
| 2671 | + } |
---|
| 2672 | + dbx500_fw_version_init(np); |
---|
| 2673 | + of_node_put(np); |
---|
2713 | 2674 | |
---|
2714 | 2675 | spin_lock_init(&mb0_transfer.lock); |
---|
2715 | 2676 | spin_lock_init(&mb0_transfer.dbb_irqs_lock); |
---|
.. | .. |
---|
2980 | 2941 | .timeout = 600, /* 10 minutes */ |
---|
2981 | 2942 | .has_28_bits_resolution = true, |
---|
2982 | 2943 | }; |
---|
2983 | | -/* |
---|
2984 | | - * Thermal Sensor |
---|
2985 | | - */ |
---|
2986 | | - |
---|
2987 | | -static struct resource db8500_thsens_resources[] = { |
---|
2988 | | - { |
---|
2989 | | - .name = "IRQ_HOTMON_LOW", |
---|
2990 | | - .start = IRQ_PRCMU_HOTMON_LOW, |
---|
2991 | | - .end = IRQ_PRCMU_HOTMON_LOW, |
---|
2992 | | - .flags = IORESOURCE_IRQ, |
---|
2993 | | - }, |
---|
2994 | | - { |
---|
2995 | | - .name = "IRQ_HOTMON_HIGH", |
---|
2996 | | - .start = IRQ_PRCMU_HOTMON_HIGH, |
---|
2997 | | - .end = IRQ_PRCMU_HOTMON_HIGH, |
---|
2998 | | - .flags = IORESOURCE_IRQ, |
---|
2999 | | - }, |
---|
3000 | | -}; |
---|
3001 | | - |
---|
3002 | | -static struct db8500_thsens_platform_data db8500_thsens_data = { |
---|
3003 | | - .trip_points[0] = { |
---|
3004 | | - .temp = 70000, |
---|
3005 | | - .type = THERMAL_TRIP_ACTIVE, |
---|
3006 | | - .cdev_name = { |
---|
3007 | | - [0] = "thermal-cpufreq-0", |
---|
3008 | | - }, |
---|
3009 | | - }, |
---|
3010 | | - .trip_points[1] = { |
---|
3011 | | - .temp = 75000, |
---|
3012 | | - .type = THERMAL_TRIP_ACTIVE, |
---|
3013 | | - .cdev_name = { |
---|
3014 | | - [0] = "thermal-cpufreq-0", |
---|
3015 | | - }, |
---|
3016 | | - }, |
---|
3017 | | - .trip_points[2] = { |
---|
3018 | | - .temp = 80000, |
---|
3019 | | - .type = THERMAL_TRIP_ACTIVE, |
---|
3020 | | - .cdev_name = { |
---|
3021 | | - [0] = "thermal-cpufreq-0", |
---|
3022 | | - }, |
---|
3023 | | - }, |
---|
3024 | | - .trip_points[3] = { |
---|
3025 | | - .temp = 85000, |
---|
3026 | | - .type = THERMAL_TRIP_CRITICAL, |
---|
3027 | | - }, |
---|
3028 | | - .num_trips = 4, |
---|
3029 | | -}; |
---|
3030 | 2944 | |
---|
3031 | 2945 | static const struct mfd_cell common_prcmu_devs[] = { |
---|
3032 | 2946 | { |
---|
.. | .. |
---|
3038 | 2952 | }; |
---|
3039 | 2953 | |
---|
3040 | 2954 | static const struct mfd_cell db8500_prcmu_devs[] = { |
---|
3041 | | - { |
---|
3042 | | - .name = "db8500-prcmu-regulators", |
---|
3043 | | - .of_compatible = "stericsson,db8500-prcmu-regulator", |
---|
3044 | | - .platform_data = &db8500_regulators, |
---|
3045 | | - .pdata_size = sizeof(db8500_regulators), |
---|
3046 | | - }, |
---|
3047 | | - { |
---|
3048 | | - .name = "cpuidle-dbx500", |
---|
3049 | | - .of_compatible = "stericsson,cpuidle-dbx500", |
---|
3050 | | - }, |
---|
3051 | | - { |
---|
3052 | | - .name = "db8500-thermal", |
---|
3053 | | - .num_resources = ARRAY_SIZE(db8500_thsens_resources), |
---|
3054 | | - .resources = db8500_thsens_resources, |
---|
3055 | | - .platform_data = &db8500_thsens_data, |
---|
3056 | | - .pdata_size = sizeof(db8500_thsens_data), |
---|
3057 | | - }, |
---|
| 2955 | + OF_MFD_CELL("db8500-prcmu-regulators", NULL, |
---|
| 2956 | + &db8500_regulators, sizeof(db8500_regulators), 0, |
---|
| 2957 | + "stericsson,db8500-prcmu-regulator"), |
---|
| 2958 | + OF_MFD_CELL("cpuidle-dbx500", |
---|
| 2959 | + NULL, NULL, 0, 0, "stericsson,cpuidle-dbx500"), |
---|
| 2960 | + OF_MFD_CELL("db8500-thermal", |
---|
| 2961 | + NULL, NULL, 0, 0, "stericsson,db8500-thermal"), |
---|
3058 | 2962 | }; |
---|
3059 | 2963 | |
---|
3060 | 2964 | static int db8500_prcmu_register_ab8500(struct device *parent) |
---|
3061 | 2965 | { |
---|
3062 | 2966 | struct device_node *np; |
---|
3063 | | - struct resource ab8500_resource; |
---|
| 2967 | + struct resource ab850x_resource; |
---|
3064 | 2968 | const struct mfd_cell ab8500_cell = { |
---|
3065 | 2969 | .name = "ab8500-core", |
---|
3066 | 2970 | .of_compatible = "stericsson,ab8500", |
---|
3067 | 2971 | .id = AB8500_VERSION_AB8500, |
---|
3068 | | - .resources = &ab8500_resource, |
---|
| 2972 | + .resources = &ab850x_resource, |
---|
3069 | 2973 | .num_resources = 1, |
---|
3070 | 2974 | }; |
---|
| 2975 | + const struct mfd_cell ab8505_cell = { |
---|
| 2976 | + .name = "ab8505-core", |
---|
| 2977 | + .of_compatible = "stericsson,ab8505", |
---|
| 2978 | + .id = AB8500_VERSION_AB8505, |
---|
| 2979 | + .resources = &ab850x_resource, |
---|
| 2980 | + .num_resources = 1, |
---|
| 2981 | + }; |
---|
| 2982 | + const struct mfd_cell *ab850x_cell; |
---|
3071 | 2983 | |
---|
3072 | 2984 | if (!parent->of_node) |
---|
3073 | 2985 | return -ENODEV; |
---|
3074 | 2986 | |
---|
3075 | 2987 | /* Look up the device node, sneak the IRQ out of it */ |
---|
3076 | 2988 | for_each_child_of_node(parent->of_node, np) { |
---|
3077 | | - if (of_device_is_compatible(np, ab8500_cell.of_compatible)) |
---|
| 2989 | + if (of_device_is_compatible(np, ab8500_cell.of_compatible)) { |
---|
| 2990 | + ab850x_cell = &ab8500_cell; |
---|
3078 | 2991 | break; |
---|
| 2992 | + } |
---|
| 2993 | + if (of_device_is_compatible(np, ab8505_cell.of_compatible)) { |
---|
| 2994 | + ab850x_cell = &ab8505_cell; |
---|
| 2995 | + break; |
---|
| 2996 | + } |
---|
3079 | 2997 | } |
---|
3080 | 2998 | if (!np) { |
---|
3081 | | - dev_info(parent, "could not find AB8500 node in the device tree\n"); |
---|
| 2999 | + dev_info(parent, "could not find AB850X node in the device tree\n"); |
---|
3082 | 3000 | return -ENODEV; |
---|
3083 | 3001 | } |
---|
3084 | | - of_irq_to_resource_table(np, &ab8500_resource, 1); |
---|
| 3002 | + of_irq_to_resource_table(np, &ab850x_resource, 1); |
---|
3085 | 3003 | |
---|
3086 | | - return mfd_add_devices(parent, 0, &ab8500_cell, 1, NULL, 0, NULL); |
---|
| 3004 | + return mfd_add_devices(parent, 0, ab850x_cell, 1, NULL, 0, NULL); |
---|
3087 | 3005 | } |
---|
3088 | 3006 | |
---|
3089 | | -/** |
---|
3090 | | - * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic |
---|
3091 | | - * |
---|
3092 | | - */ |
---|
3093 | 3007 | static int db8500_prcmu_probe(struct platform_device *pdev) |
---|
3094 | 3008 | { |
---|
3095 | 3009 | struct device_node *np = pdev->dev.of_node; |
---|
.. | .. |
---|
3108 | 3022 | return -ENOMEM; |
---|
3109 | 3023 | } |
---|
3110 | 3024 | init_prcm_registers(); |
---|
3111 | | - dbx500_fw_version_init(pdev, DB8500_PRCMU_FW_VERSION_OFFSET); |
---|
3112 | 3025 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm"); |
---|
3113 | 3026 | if (!res) { |
---|
3114 | 3027 | dev_err(&pdev->dev, "no prcmu tcdm region provided\n"); |
---|
.. | .. |
---|
3126 | 3039 | writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); |
---|
3127 | 3040 | |
---|
3128 | 3041 | irq = platform_get_irq(pdev, 0); |
---|
3129 | | - if (irq <= 0) { |
---|
3130 | | - dev_err(&pdev->dev, "no prcmu irq provided\n"); |
---|
| 3042 | + if (irq <= 0) |
---|
3131 | 3043 | return irq; |
---|
3132 | | - } |
---|
3133 | 3044 | |
---|
3134 | 3045 | err = request_threaded_irq(irq, prcmu_irq_handler, |
---|
3135 | 3046 | prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL); |
---|
.. | .. |
---|
3188 | 3099 | { |
---|
3189 | 3100 | return platform_driver_register(&db8500_prcmu_driver); |
---|
3190 | 3101 | } |
---|
3191 | | - |
---|
3192 | 3102 | core_initcall(db8500_prcmu_init); |
---|
3193 | | - |
---|
3194 | | -MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com>"); |
---|
3195 | | -MODULE_DESCRIPTION("DB8500 PRCM Unit driver"); |
---|
3196 | | -MODULE_LICENSE("GPL v2"); |
---|