aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 17:58:40 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 17:58:40 -0500
commitb274776c54c320763bc12eb035c0e244f76ccb43 (patch)
treec75b70d0824a7ae029229b19d61884039abf2127 /drivers/mfd
parentb24174b0cbbe383c5bb6097aeb24480b8fd2d338 (diff)
parent3b1209e7994c4d31ff9932a7f566ae1c96b3c443 (diff)
Merge tag 'cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC cleanups from Arnd Bergmann: "A large number of cleanups, all over the platforms. This is dominated largely by the Samsung platforms (s3c, s5p, exynos) and a few of the others moving code out of arch/arm into more appropriate subsystems. The clocksource and irqchip drivers are now abstracted to the point where platforms that are already cleaned up do not need to even specify the driver they use, it can all get configured from the device tree as we do for normal device drivers. The clocksource changes basically touch every single platform in the process. We further clean up the use of platform specific header files here, with the goal of turning more of the platforms over to being "multiplatform" enabled, which implies that they cannot expose their headers to architecture independent code any more. It is expected that no functional changes are part of the cleanup. The overall reduction in total code lines is mostly the result of removing broken and obsolete code." * tag 'cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (133 commits) ARM: mvebu: correct gated clock documentation ARM: kirkwood: add missing include for nsa310 ARM: exynos: move exynos4210-combiner to drivers/irqchip mfd: db8500-prcmu: update resource passing drivers/db8500-cpufreq: delete dangling include ARM: at91: remove NEOCORE 926 board sunxi: Cleanup the reset code and add meaningful registers defines ARM: S3C24XX: header mach/regs-mem.h local ARM: S3C24XX: header mach/regs-power.h local ARM: S3C24XX: header mach/regs-s3c2412-mem.h local ARM: S3C24XX: Remove plat-s3c24xx directory in arch/arm/ ARM: S3C24XX: transform s3c2443 subirqs into new structure ARM: S3C24XX: modify s3c2443 irq init to initialize all irqs ARM: S3C24XX: move s3c2443 irq code to irq.c ARM: S3C24XX: transform s3c2416 irqs into new structure ARM: S3C24XX: modify s3c2416 irq init to initialize all irqs ARM: S3C24XX: move s3c2416 irq init to common irq code ARM: S3C24XX: Modify s3c_irq_wake to use the hwirq property ARM: S3C24XX: Move irq syscore-ops to irq-pm clocksource: always define CLOCKSOURCE_OF_DECLARE ...
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/db8500-prcmu.c139
1 files changed, 85 insertions, 54 deletions
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 268f45d42394..1192518e1aca 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -26,22 +26,18 @@
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>
29#include <linux/mfd/core.h> 30#include <linux/mfd/core.h>
30#include <linux/mfd/dbx500-prcmu.h> 31#include <linux/mfd/dbx500-prcmu.h>
31#include <linux/mfd/abx500/ab8500.h> 32#include <linux/mfd/abx500/ab8500.h>
32#include <linux/regulator/db8500-prcmu.h> 33#include <linux/regulator/db8500-prcmu.h>
33#include <linux/regulator/machine.h> 34#include <linux/regulator/machine.h>
34#include <linux/cpufreq.h> 35#include <linux/cpufreq.h>
35#include <asm/hardware/gic.h>
36#include <mach/hardware.h> 36#include <mach/hardware.h>
37#include <mach/irqs.h> 37#include <mach/irqs.h>
38#include <mach/db8500-regs.h> 38#include <mach/db8500-regs.h>
39#include <mach/id.h>
40#include "dbx500-prcmu-regs.h" 39#include "dbx500-prcmu-regs.h"
41 40
42/* Offset for the firmware version within the TCPM */
43#define PRCMU_FW_VERSION_OFFSET 0xA4
44
45/* Index of different voltages to be used when accessing AVSData */ 41/* Index of different voltages to be used when accessing AVSData */
46#define PRCM_AVS_BASE 0x2FC 42#define PRCM_AVS_BASE 0x2FC
47#define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0) 43#define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0)
@@ -216,10 +212,8 @@
216#define PRCM_REQ_MB5_I2C_HW_BITS (PRCM_REQ_MB5 + 0x1) 212#define PRCM_REQ_MB5_I2C_HW_BITS (PRCM_REQ_MB5 + 0x1)
217#define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 0x2) 213#define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 0x2)
218#define PRCM_REQ_MB5_I2C_VAL (PRCM_REQ_MB5 + 0x3) 214#define PRCM_REQ_MB5_I2C_VAL (PRCM_REQ_MB5 + 0x3)
219#define PRCMU_I2C_WRITE(slave) \ 215#define PRCMU_I2C_WRITE(slave) (((slave) << 1) | BIT(6))
220 (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0)) 216#define PRCMU_I2C_READ(slave) (((slave) << 1) | BIT(0) | BIT(6))
221#define PRCMU_I2C_READ(slave) \
222 (((slave) << 1) | BIT(0) | (cpu_is_u8500v2() ? BIT(6) : 0))
223#define PRCMU_I2C_STOP_EN BIT(3) 217#define PRCMU_I2C_STOP_EN BIT(3)
224 218
225/* Mailbox 5 ACKs */ 219/* Mailbox 5 ACKs */
@@ -1049,12 +1043,13 @@ int db8500_prcmu_get_ddr_opp(void)
1049 * 1043 *
1050 * This function sets the operating point of the DDR. 1044 * This function sets the operating point of the DDR.
1051 */ 1045 */
1046static bool enable_set_ddr_opp;
1052int db8500_prcmu_set_ddr_opp(u8 opp) 1047int db8500_prcmu_set_ddr_opp(u8 opp)
1053{ 1048{
1054 if (opp < DDR_100_OPP || opp > DDR_25_OPP) 1049 if (opp < DDR_100_OPP || opp > DDR_25_OPP)
1055 return -EINVAL; 1050 return -EINVAL;
1056 /* Changing the DDR OPP can hang the hardware pre-v21 */ 1051 /* Changing the DDR OPP can hang the hardware pre-v21 */
1057 if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20()) 1052 if (enable_set_ddr_opp)
1058 writeb(opp, PRCM_DDR_SUBSYS_APE_MINBW); 1053 writeb(opp, PRCM_DDR_SUBSYS_APE_MINBW);
1059 1054
1060 return 0; 1055 return 0;
@@ -2706,21 +2701,43 @@ static struct irq_chip prcmu_irq_chip = {
2706 .irq_unmask = prcmu_irq_unmask, 2701 .irq_unmask = prcmu_irq_unmask,
2707}; 2702};
2708 2703
2709static char *fw_project_name(u8 project) 2704static __init char *fw_project_name(u32 project)
2710{ 2705{
2711 switch (project) { 2706 switch (project) {
2712 case PRCMU_FW_PROJECT_U8500: 2707 case PRCMU_FW_PROJECT_U8500:
2713 return "U8500"; 2708 return "U8500";
2714 case PRCMU_FW_PROJECT_U8500_C2: 2709 case PRCMU_FW_PROJECT_U8400:
2715 return "U8500 C2"; 2710 return "U8400";
2716 case PRCMU_FW_PROJECT_U9500: 2711 case PRCMU_FW_PROJECT_U9500:
2717 return "U9500"; 2712 return "U9500";
2718 case PRCMU_FW_PROJECT_U9500_C2: 2713 case PRCMU_FW_PROJECT_U8500_MBB:
2719 return "U9500 C2"; 2714 return "U8500 MBB";
2715 case PRCMU_FW_PROJECT_U8500_C1:
2716 return "U8500 C1";
2717 case PRCMU_FW_PROJECT_U8500_C2:
2718 return "U8500 C2";
2719 case PRCMU_FW_PROJECT_U8500_C3:
2720 return "U8500 C3";
2721 case PRCMU_FW_PROJECT_U8500_C4:
2722 return "U8500 C4";
2723 case PRCMU_FW_PROJECT_U9500_MBL:
2724 return "U9500 MBL";
2725 case PRCMU_FW_PROJECT_U8500_MBL:
2726 return "U8500 MBL";
2727 case PRCMU_FW_PROJECT_U8500_MBL2:
2728 return "U8500 MBL2";
2720 case PRCMU_FW_PROJECT_U8520: 2729 case PRCMU_FW_PROJECT_U8520:
2721 return "U8520"; 2730 return "U8520 MBL";
2722 case PRCMU_FW_PROJECT_U8420: 2731 case PRCMU_FW_PROJECT_U8420:
2723 return "U8420"; 2732 return "U8420";
2733 case PRCMU_FW_PROJECT_U9540:
2734 return "U9540";
2735 case PRCMU_FW_PROJECT_A9420:
2736 return "A9420";
2737 case PRCMU_FW_PROJECT_L8540:
2738 return "L8540";
2739 case PRCMU_FW_PROJECT_L8580:
2740 return "L8580";
2724 default: 2741 default:
2725 return "Unknown"; 2742 return "Unknown";
2726 } 2743 }
@@ -2766,36 +2783,44 @@ static int db8500_irq_init(struct device_node *np)
2766 return 0; 2783 return 0;
2767} 2784}
2768 2785
2769void __init db8500_prcmu_early_init(void) 2786static void dbx500_fw_version_init(struct platform_device *pdev,
2787 u32 version_offset)
2770{ 2788{
2771 if (cpu_is_u8500v2() || cpu_is_u9540()) { 2789 struct resource *res;
2772 void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K); 2790 void __iomem *tcpm_base;
2773
2774 if (tcpm_base != NULL) {
2775 u32 version;
2776 version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET);
2777 fw_info.version.project = version & 0xFF;
2778 fw_info.version.api_version = (version >> 8) & 0xFF;
2779 fw_info.version.func_version = (version >> 16) & 0xFF;
2780 fw_info.version.errata = (version >> 24) & 0xFF;
2781 fw_info.valid = true;
2782 pr_info("PRCMU firmware: %s, version %d.%d.%d\n",
2783 fw_project_name(fw_info.version.project),
2784 (version >> 8) & 0xFF, (version >> 16) & 0xFF,
2785 (version >> 24) & 0xFF);
2786 iounmap(tcpm_base);
2787 }
2788 2791
2789 if (cpu_is_u9540()) 2792 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
2790 tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE, 2793 "prcmu-tcpm");
2791 SZ_4K + SZ_8K) + SZ_8K; 2794 if (!res) {
2792 else 2795 dev_err(&pdev->dev,
2793 tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); 2796 "Error: no prcmu tcpm memory region provided\n");
2794 } else { 2797 return;
2795 pr_err("prcmu: Unsupported chip version\n");
2796 BUG();
2797 } 2798 }
2799 tcpm_base = ioremap(res->start, resource_size(res));
2800 if (tcpm_base != NULL) {
2801 u32 version;
2802
2803 version = readl(tcpm_base + version_offset);
2804 fw_info.version.project = (version & 0xFF);
2805 fw_info.version.api_version = (version >> 8) & 0xFF;
2806 fw_info.version.func_version = (version >> 16) & 0xFF;
2807 fw_info.version.errata = (version >> 24) & 0xFF;
2808 strncpy(fw_info.version.project_name,
2809 fw_project_name(fw_info.version.project),
2810 PRCMU_FW_PROJECT_NAME_LEN);
2811 fw_info.valid = true;
2812 pr_info("PRCMU firmware: %s(%d), version %d.%d.%d\n",
2813 fw_info.version.project_name,
2814 fw_info.version.project,
2815 fw_info.version.api_version,
2816 fw_info.version.func_version,
2817 fw_info.version.errata);
2818 iounmap(tcpm_base);
2819 }
2820}
2798 2821
2822void __init db8500_prcmu_early_init(void)
2823{
2799 spin_lock_init(&mb0_transfer.lock); 2824 spin_lock_init(&mb0_transfer.lock);
2800 spin_lock_init(&mb0_transfer.dbb_irqs_lock); 2825 spin_lock_init(&mb0_transfer.dbb_irqs_lock);
2801 mutex_init(&mb0_transfer.ac_wake_lock); 2826 mutex_init(&mb0_transfer.ac_wake_lock);
@@ -3105,23 +3130,30 @@ static void db8500_prcmu_update_cpufreq(void)
3105 */ 3130 */
3106static int db8500_prcmu_probe(struct platform_device *pdev) 3131static int db8500_prcmu_probe(struct platform_device *pdev)
3107{ 3132{
3108 struct ab8500_platform_data *ab8500_platdata = pdev->dev.platform_data;
3109 struct device_node *np = pdev->dev.of_node; 3133 struct device_node *np = pdev->dev.of_node;
3134 struct prcmu_pdata *pdata = dev_get_platdata(&pdev->dev);
3110 int irq = 0, err = 0, i; 3135 int irq = 0, err = 0, i;
3111 3136 struct resource *res;
3112 if (ux500_is_svp())
3113 return -ENODEV;
3114 3137
3115 init_prcm_registers(); 3138 init_prcm_registers();
3116 3139
3140 dbx500_fw_version_init(pdev, pdata->version_offset);
3141 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
3142 if (!res) {
3143 dev_err(&pdev->dev, "no prcmu tcdm region provided\n");
3144 return -ENOENT;
3145 }
3146 tcdm_base = devm_ioremap(&pdev->dev, res->start,
3147 resource_size(res));
3148
3117 /* Clean up the mailbox interrupts after pre-kernel code. */ 3149 /* Clean up the mailbox interrupts after pre-kernel code. */
3118 writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); 3150 writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
3119 3151
3120 if (np) 3152 irq = platform_get_irq(pdev, 0);
3121 irq = platform_get_irq(pdev, 0); 3153 if (irq <= 0) {
3122 3154 dev_err(&pdev->dev, "no prcmu irq provided\n");
3123 if (!np || irq <= 0) 3155 return -ENOENT;
3124 irq = IRQ_DB8500_PRCMU1; 3156 }
3125 3157
3126 err = request_threaded_irq(irq, prcmu_irq_handler, 3158 err = request_threaded_irq(irq, prcmu_irq_handler,
3127 prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL); 3159 prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
@@ -3135,13 +3167,12 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
3135 3167
3136 for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) { 3168 for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) {
3137 if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) { 3169 if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) {
3138 db8500_prcmu_devs[i].platform_data = ab8500_platdata; 3170 db8500_prcmu_devs[i].platform_data = pdata->ab_platdata;
3139 db8500_prcmu_devs[i].pdata_size = sizeof(struct ab8500_platform_data); 3171 db8500_prcmu_devs[i].pdata_size = sizeof(struct ab8500_platform_data);
3140 } 3172 }
3141 } 3173 }
3142 3174
3143 if (cpu_is_u8500v20_or_later()) 3175 prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
3144 prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
3145 3176
3146 db8500_prcmu_update_cpufreq(); 3177 db8500_prcmu_update_cpufreq();
3147 3178