aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/db8500-prcmu.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2013-02-07 04:17:31 -0500
committerLinus Walleij <linus.walleij@linaro.org>2013-02-12 06:44:27 -0500
commit05ec260edecaf3dc214cff49d43b1ad9b2cbb710 (patch)
tree7ce97e53a8098a9045191e302c8d9b06319133ac /drivers/mfd/db8500-prcmu.c
parentf25610ce535304f7c2420970d1315c6c4fce157c (diff)
mfd: db8500-prcmu: update resource passing
When trying to get rid of the cross-includes of <mach/id.h> from different drivers, so we can localize ASIC/CPU detection to the mach-ux500 folder, we run into the way the PRCMU handles base addresses and firmware detection. This patch updates the firmware version detection to pass the required information as platform data instead of relying on cpu_is_* macros. Now the PRCMU base address, the secondary TCDM area, the TCPM area and the IRQ are passed as resources instead of being grabbed from <mach/*> files. Incidentally this also removes part of the reliance on <mach/irqs.h>. Further it updates the firmware version detection, since the location of the firmware ID bytes in the designated memory are is now passed from the platform data instead. There is no reason not to include the nice split-off of a struct to hold the firmware information and a separate function to populate it. The patch actually rids the need to use the external db8500_prcmu_early_init call at all, but I'm keepin back that removal as I don't want the patch to be too big. Cc: arm@kernel.org Cc: Michel Jaoen <michel.jaouen@stericsson.com> Cc: Lee Jones <lee.jones@linaro.org> Acked-by: Samuel Ortiz <sameo@linux.intel.com> Acked-by: Loic Pallardy <loic.pallardy@stericsson.com> Acked-by: Fabio Baltieri <fabio.baltieri@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/mfd/db8500-prcmu.c')
-rw-r--r--drivers/mfd/db8500-prcmu.c122
1 files changed, 79 insertions, 43 deletions
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 67d8b25d183e..eba03d2329dd 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -38,9 +38,6 @@
38#include <mach/db8500-regs.h> 38#include <mach/db8500-regs.h>
39#include "dbx500-prcmu-regs.h" 39#include "dbx500-prcmu-regs.h"
40 40
41/* Offset for the firmware version within the TCPM */
42#define PRCMU_FW_VERSION_OFFSET 0xA4
43
44/* Index of different voltages to be used when accessing AVSData */ 41/* Index of different voltages to be used when accessing AVSData */
45#define PRCM_AVS_BASE 0x2FC 42#define PRCM_AVS_BASE 0x2FC
46#define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0) 43#define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0)
@@ -2704,21 +2701,43 @@ static struct irq_chip prcmu_irq_chip = {
2704 .irq_unmask = prcmu_irq_unmask, 2701 .irq_unmask = prcmu_irq_unmask,
2705}; 2702};
2706 2703
2707static char *fw_project_name(u8 project) 2704static __init char *fw_project_name(u32 project)
2708{ 2705{
2709 switch (project) { 2706 switch (project) {
2710 case PRCMU_FW_PROJECT_U8500: 2707 case PRCMU_FW_PROJECT_U8500:
2711 return "U8500"; 2708 return "U8500";
2712 case PRCMU_FW_PROJECT_U8500_C2: 2709 case PRCMU_FW_PROJECT_U8400:
2713 return "U8500 C2"; 2710 return "U8400";
2714 case PRCMU_FW_PROJECT_U9500: 2711 case PRCMU_FW_PROJECT_U9500:
2715 return "U9500"; 2712 return "U9500";
2716 case PRCMU_FW_PROJECT_U9500_C2: 2713 case PRCMU_FW_PROJECT_U8500_MBB:
2717 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";
2718 case PRCMU_FW_PROJECT_U8520: 2729 case PRCMU_FW_PROJECT_U8520:
2719 return "U8520"; 2730 return "U8520 MBL";
2720 case PRCMU_FW_PROJECT_U8420: 2731 case PRCMU_FW_PROJECT_U8420:
2721 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";
2722 default: 2741 default:
2723 return "Unknown"; 2742 return "Unknown";
2724 } 2743 }
@@ -2759,37 +2778,44 @@ static int db8500_irq_init(struct device_node *np)
2759 return 0; 2778 return 0;
2760} 2779}
2761 2780
2762void __init db8500_prcmu_early_init(void) 2781static void dbx500_fw_version_init(struct platform_device *pdev,
2782 u32 version_offset)
2763{ 2783{
2764 if (cpu_is_u8500v2() || cpu_is_u9540()) { 2784 struct resource *res;
2765 void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K); 2785 void __iomem *tcpm_base;
2766
2767 if (tcpm_base != NULL) {
2768 u32 version;
2769 version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET);
2770 fw_info.version.project = version & 0xFF;
2771 fw_info.version.api_version = (version >> 8) & 0xFF;
2772 fw_info.version.func_version = (version >> 16) & 0xFF;
2773 fw_info.version.errata = (version >> 24) & 0xFF;
2774 fw_info.valid = true;
2775 pr_info("PRCMU firmware: %s, version %d.%d.%d\n",
2776 fw_project_name(fw_info.version.project),
2777 (version >> 8) & 0xFF, (version >> 16) & 0xFF,
2778 (version >> 24) & 0xFF);
2779 iounmap(tcpm_base);
2780 }
2781 2786
2782 if (cpu_is_u9540()) 2787 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
2783 tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE, 2788 "prcmu-tcpm");
2784 SZ_4K + SZ_8K) + SZ_8K; 2789 if (!res) {
2785 else 2790 dev_err(&pdev->dev,
2786 tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); 2791 "Error: no prcmu tcpm memory region provided\n");
2787 } else { 2792 return;
2788 pr_err("prcmu: Unsupported chip version\n"); 2793 }
2789 BUG(); 2794 tcpm_base = ioremap(res->start, resource_size(res));
2795 if (tcpm_base != NULL) {
2796 u32 version;
2797
2798 version = readl(tcpm_base + version_offset);
2799 fw_info.version.project = (version & 0xFF);
2800 fw_info.version.api_version = (version >> 8) & 0xFF;
2801 fw_info.version.func_version = (version >> 16) & 0xFF;
2802 fw_info.version.errata = (version >> 24) & 0xFF;
2803 strncpy(fw_info.version.project_name,
2804 fw_project_name(fw_info.version.project),
2805 PRCMU_FW_PROJECT_NAME_LEN);
2806 fw_info.valid = true;
2807 pr_info("PRCMU firmware: %s(%d), version %d.%d.%d\n",
2808 fw_info.version.project_name,
2809 fw_info.version.project,
2810 fw_info.version.api_version,
2811 fw_info.version.func_version,
2812 fw_info.version.errata);
2813 iounmap(tcpm_base);
2790 } 2814 }
2791 tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); 2815}
2792 2816
2817void __init db8500_prcmu_early_init(void)
2818{
2793 spin_lock_init(&mb0_transfer.lock); 2819 spin_lock_init(&mb0_transfer.lock);
2794 spin_lock_init(&mb0_transfer.dbb_irqs_lock); 2820 spin_lock_init(&mb0_transfer.dbb_irqs_lock);
2795 mutex_init(&mb0_transfer.ac_wake_lock); 2821 mutex_init(&mb0_transfer.ac_wake_lock);
@@ -3099,20 +3125,30 @@ static void db8500_prcmu_update_cpufreq(void)
3099 */ 3125 */
3100static int db8500_prcmu_probe(struct platform_device *pdev) 3126static int db8500_prcmu_probe(struct platform_device *pdev)
3101{ 3127{
3102 struct ab8500_platform_data *ab8500_platdata = pdev->dev.platform_data;
3103 struct device_node *np = pdev->dev.of_node; 3128 struct device_node *np = pdev->dev.of_node;
3129 struct prcmu_pdata *pdata = dev_get_platdata(&pdev->dev);
3104 int irq = 0, err = 0, i; 3130 int irq = 0, err = 0, i;
3131 struct resource *res;
3105 3132
3106 init_prcm_registers(); 3133 init_prcm_registers();
3107 3134
3135 dbx500_fw_version_init(pdev, pdata->version_offset);
3136 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
3137 if (!res) {
3138 dev_err(&pdev->dev, "no prcmu tcdm region provided\n");
3139 return -ENOENT;
3140 }
3141 tcdm_base = devm_ioremap(&pdev->dev, res->start,
3142 resource_size(res));
3143
3108 /* Clean up the mailbox interrupts after pre-kernel code. */ 3144 /* Clean up the mailbox interrupts after pre-kernel code. */
3109 writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); 3145 writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
3110 3146
3111 if (np) 3147 irq = platform_get_irq(pdev, 0);
3112 irq = platform_get_irq(pdev, 0); 3148 if (irq <= 0) {
3113 3149 dev_err(&pdev->dev, "no prcmu irq provided\n");
3114 if (!np || irq <= 0) 3150 return -ENOENT;
3115 irq = IRQ_DB8500_PRCMU1; 3151 }
3116 3152
3117 err = request_threaded_irq(irq, prcmu_irq_handler, 3153 err = request_threaded_irq(irq, prcmu_irq_handler,
3118 prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL); 3154 prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
@@ -3126,7 +3162,7 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
3126 3162
3127 for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) { 3163 for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) {
3128 if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) { 3164 if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) {
3129 db8500_prcmu_devs[i].platform_data = ab8500_platdata; 3165 db8500_prcmu_devs[i].platform_data = pdata->ab_platdata;
3130 db8500_prcmu_devs[i].pdata_size = sizeof(struct ab8500_platform_data); 3166 db8500_prcmu_devs[i].pdata_size = sizeof(struct ab8500_platform_data);
3131 } 3167 }
3132 } 3168 }