Merge tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Feb 2013 23:12:17 +0000 (15:12 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Feb 2013 23:12:18 +0000 (15:12 -0800)
Pull ARM SoC driver specific changes from Arnd Bergmann:

 - Updates to the ux500 cpufreq code

 - Moving the u300 DMA controller driver to drivers/dma

 - Moving versatile express drivers out of arch/arm for sharing with arch/arm64

 - Device tree bindings for the OMAP General Purpose Memory Controller

* tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (27 commits)
  ARM: OMAP2+: gpmc: Add device tree documentation for elm handle
  ARM: OMAP2+: gpmc: add DT bindings for OneNAND
  ARM: OMAP2+: gpmc-onenand: drop __init annotation
  mtd: omap-onenand: pass device_node in platform data
  ARM: OMAP2+: Prevent potential crash if GPMC probe fails
  ARM: OMAP2+: gpmc: Remove unneeded of_node_put()
  arm: Move sp810.h to include/linux/amba/
  ARM: OMAP: gpmc: add DT bindings for GPMC timings and NAND
  ARM: OMAP: gpmc: enable hwecc for AM33xx SoCs
  ARM: OMAP: gpmc-nand: drop __init annotation
  mtd: omap-nand: pass device_node in platform data
  ARM: OMAP: gpmc: don't create devices from initcall on DT
  dma: coh901318: cut down on platform data abstraction
  dma: coh901318: merge header files
  dma: coh901318: push definitions into driver
  dma: coh901318: push header down into the DMA subsystem
  dma: coh901318: skip hard-coded addresses
  dma: coh901318: remove hardcoded target addresses
  dma: coh901318: push platform data into driver
  dma: coh901318: create a proper platform data file
  ...

1  2 
arch/arm/mach-omap2/gpmc.c
drivers/clk/versatile/clk-vexpress.c
drivers/cpufreq/Makefile
drivers/cpufreq/dbx500-cpufreq.c
drivers/mfd/db8500-prcmu.c

index 64bac53da0e8f697238e446af9e76d0f1d532a9b,1adb2d4496f6ffc095c1bc29fecad8c750ac6326..03d771349be6e058966bdfdcca35f28336e3eabf
  #include <linux/module.h>
  #include <linux/interrupt.h>
  #include <linux/platform_device.h>
+ #include <linux/of.h>
+ #include <linux/of_mtd.h>
+ #include <linux/of_device.h>
+ #include <linux/mtd/nand.h>
  
  #include <linux/platform_data/mtd-nand-omap2.h>
  
@@@ -34,6 -38,8 +38,8 @@@
  #include "common.h"
  #include "omap_device.h"
  #include "gpmc.h"
+ #include "gpmc-nand.h"
+ #include "gpmc-onenand.h"
  
  #define       DEVICE_NAME             "omap-gpmc"
  
@@@ -145,7 -151,8 +151,8 @@@ static unsigned gpmc_irq_start
  static struct resource        gpmc_mem_root;
  static struct resource        gpmc_cs_mem[GPMC_CS_NUM];
  static DEFINE_SPINLOCK(gpmc_mem_lock);
- static unsigned int gpmc_cs_map;      /* flag for cs which are initialized */
+ /* Define chip-selects as reserved by default until probe completes */
+ static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1);
  static struct device *gpmc_dev;
  static int gpmc_irq;
  static resource_size_t phys_base, mem_size;
@@@ -1118,9 -1125,216 +1125,216 @@@ int gpmc_calc_timings(struct gpmc_timin
        /* TODO: remove, see function definition */
        gpmc_convert_ps_to_ns(gpmc_t);
  
+       /* Now the GPMC is initialised, unreserve the chip-selects */
+       gpmc_cs_map = 0;
        return 0;
  }
  
+ #ifdef CONFIG_OF
+ static struct of_device_id gpmc_dt_ids[] = {
+       { .compatible = "ti,omap2420-gpmc" },
+       { .compatible = "ti,omap2430-gpmc" },
+       { .compatible = "ti,omap3430-gpmc" },   /* omap3430 & omap3630 */
+       { .compatible = "ti,omap4430-gpmc" },   /* omap4430 & omap4460 & omap543x */
+       { .compatible = "ti,am3352-gpmc" },     /* am335x devices */
+       { }
+ };
+ MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
+ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
+                                               struct gpmc_timings *gpmc_t)
+ {
+       u32 val;
+       memset(gpmc_t, 0, sizeof(*gpmc_t));
+       /* minimum clock period for syncronous mode */
+       if (!of_property_read_u32(np, "gpmc,sync-clk", &val))
+               gpmc_t->sync_clk = val;
+       /* chip select timtings */
+       if (!of_property_read_u32(np, "gpmc,cs-on", &val))
+               gpmc_t->cs_on = val;
+       if (!of_property_read_u32(np, "gpmc,cs-rd-off", &val))
+               gpmc_t->cs_rd_off = val;
+       if (!of_property_read_u32(np, "gpmc,cs-wr-off", &val))
+               gpmc_t->cs_wr_off = val;
+       /* ADV signal timings */
+       if (!of_property_read_u32(np, "gpmc,adv-on", &val))
+               gpmc_t->adv_on = val;
+       if (!of_property_read_u32(np, "gpmc,adv-rd-off", &val))
+               gpmc_t->adv_rd_off = val;
+       if (!of_property_read_u32(np, "gpmc,adv-wr-off", &val))
+               gpmc_t->adv_wr_off = val;
+       /* WE signal timings */
+       if (!of_property_read_u32(np, "gpmc,we-on", &val))
+               gpmc_t->we_on = val;
+       if (!of_property_read_u32(np, "gpmc,we-off", &val))
+               gpmc_t->we_off = val;
+       /* OE signal timings */
+       if (!of_property_read_u32(np, "gpmc,oe-on", &val))
+               gpmc_t->oe_on = val;
+       if (!of_property_read_u32(np, "gpmc,oe-off", &val))
+               gpmc_t->oe_off = val;
+       /* access and cycle timings */
+       if (!of_property_read_u32(np, "gpmc,page-burst-access", &val))
+               gpmc_t->page_burst_access = val;
+       if (!of_property_read_u32(np, "gpmc,access", &val))
+               gpmc_t->access = val;
+       if (!of_property_read_u32(np, "gpmc,rd-cycle", &val))
+               gpmc_t->rd_cycle = val;
+       if (!of_property_read_u32(np, "gpmc,wr-cycle", &val))
+               gpmc_t->wr_cycle = val;
+       /* only for OMAP3430 */
+       if (!of_property_read_u32(np, "gpmc,wr-access", &val))
+               gpmc_t->wr_access = val;
+       if (!of_property_read_u32(np, "gpmc,wr-data-mux-bus", &val))
+               gpmc_t->wr_data_mux_bus = val;
+ }
+ #ifdef CONFIG_MTD_NAND
+ static const char * const nand_ecc_opts[] = {
+       [OMAP_ECC_HAMMING_CODE_DEFAULT]         = "sw",
+       [OMAP_ECC_HAMMING_CODE_HW]              = "hw",
+       [OMAP_ECC_HAMMING_CODE_HW_ROMCODE]      = "hw-romcode",
+       [OMAP_ECC_BCH4_CODE_HW]                 = "bch4",
+       [OMAP_ECC_BCH8_CODE_HW]                 = "bch8",
+ };
+ static int gpmc_probe_nand_child(struct platform_device *pdev,
+                                struct device_node *child)
+ {
+       u32 val;
+       const char *s;
+       struct gpmc_timings gpmc_t;
+       struct omap_nand_platform_data *gpmc_nand_data;
+       if (of_property_read_u32(child, "reg", &val) < 0) {
+               dev_err(&pdev->dev, "%s has no 'reg' property\n",
+                       child->full_name);
+               return -ENODEV;
+       }
+       gpmc_nand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_nand_data),
+                                     GFP_KERNEL);
+       if (!gpmc_nand_data)
+               return -ENOMEM;
+       gpmc_nand_data->cs = val;
+       gpmc_nand_data->of_node = child;
+       if (!of_property_read_string(child, "ti,nand-ecc-opt", &s))
+               for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++)
+                       if (!strcasecmp(s, nand_ecc_opts[val])) {
+                               gpmc_nand_data->ecc_opt = val;
+                               break;
+                       }
+       val = of_get_nand_bus_width(child);
+       if (val == 16)
+               gpmc_nand_data->devsize = NAND_BUSWIDTH_16;
+       gpmc_read_timings_dt(child, &gpmc_t);
+       gpmc_nand_init(gpmc_nand_data, &gpmc_t);
+       return 0;
+ }
+ #else
+ static int gpmc_probe_nand_child(struct platform_device *pdev,
+                                struct device_node *child)
+ {
+       return 0;
+ }
+ #endif
+ #ifdef CONFIG_MTD_ONENAND
+ static int gpmc_probe_onenand_child(struct platform_device *pdev,
+                                struct device_node *child)
+ {
+       u32 val;
+       struct omap_onenand_platform_data *gpmc_onenand_data;
+       if (of_property_read_u32(child, "reg", &val) < 0) {
+               dev_err(&pdev->dev, "%s has no 'reg' property\n",
+                       child->full_name);
+               return -ENODEV;
+       }
+       gpmc_onenand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_onenand_data),
+                                        GFP_KERNEL);
+       if (!gpmc_onenand_data)
+               return -ENOMEM;
+       gpmc_onenand_data->cs = val;
+       gpmc_onenand_data->of_node = child;
+       gpmc_onenand_data->dma_channel = -1;
+       if (!of_property_read_u32(child, "dma-channel", &val))
+               gpmc_onenand_data->dma_channel = val;
+       gpmc_onenand_init(gpmc_onenand_data);
+       return 0;
+ }
+ #else
+ static int gpmc_probe_onenand_child(struct platform_device *pdev,
+                                   struct device_node *child)
+ {
+       return 0;
+ }
+ #endif
+ static int gpmc_probe_dt(struct platform_device *pdev)
+ {
+       int ret;
+       struct device_node *child;
+       const struct of_device_id *of_id =
+               of_match_device(gpmc_dt_ids, &pdev->dev);
+       if (!of_id)
+               return 0;
+       for_each_node_by_name(child, "nand") {
+               ret = gpmc_probe_nand_child(pdev, child);
+               if (ret < 0) {
+                       of_node_put(child);
+                       return ret;
+               }
+       }
+       for_each_node_by_name(child, "onenand") {
+               ret = gpmc_probe_onenand_child(pdev, child);
+               if (ret < 0) {
+                       of_node_put(child);
+                       return ret;
+               }
+       }
+       return 0;
+ }
+ #else
+ static int gpmc_probe_dt(struct platform_device *pdev)
+ {
+       return 0;
+ }
+ #endif
  static int gpmc_probe(struct platform_device *pdev)
  {
        int rc;
        phys_base = res->start;
        mem_size = resource_size(res);
  
 -      gpmc_base = devm_request_and_ioremap(&pdev->dev, res);
 -      if (!gpmc_base) {
 -              dev_err(&pdev->dev, "error: request memory / ioremap\n");
 -              return -EADDRNOTAVAIL;
 -      }
 +      gpmc_base = devm_ioremap_resource(&pdev->dev, res);
 +      if (IS_ERR(gpmc_base))
 +              return PTR_ERR(gpmc_base);
  
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (res == NULL)
        if (IS_ERR_VALUE(gpmc_setup_irq()))
                dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
  
+       rc = gpmc_probe_dt(pdev);
+       if (rc < 0) {
+               clk_disable_unprepare(gpmc_l3_clk);
+               clk_put(gpmc_l3_clk);
+               dev_err(gpmc_dev, "failed to probe DT parameters\n");
+               return rc;
+       }
        return 0;
  }
  
@@@ -1189,6 -1413,7 +1411,7 @@@ static struct platform_driver gpmc_driv
        .driver         = {
                .name   = DEVICE_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(gpmc_dt_ids),
        },
  };
  
@@@ -1212,6 -1437,13 +1435,13 @@@ static int __init omap_gpmc_init(void
        struct platform_device *pdev;
        char *oh_name = "gpmc";
  
+       /*
+        * if the board boots up with a populated DT, do not
+        * manually add the device from this initcall
+        */
+       if (of_have_populated_dt())
+               return -ENODEV;
        oh = omap_hwmod_lookup(oh_name);
        if (!oh) {
                pr_err("Could not look up %s\n", oh_name);
index f889f2f07b370338ee5f2e9a97053ba83005fc13,4f83ff9ab2d98749fef15e95e5b4cebbde7d0ea1..82b45aad8ccfe39354148afae46eee19f3bbfc5f
@@@ -11,6 -11,7 +11,7 @@@
   * Copyright (C) 2012 ARM Limited
   */
  
+ #include <linux/amba/sp810.h>
  #include <linux/clkdev.h>
  #include <linux/clk-provider.h>
  #include <linux/err.h>
@@@ -18,8 -19,6 +19,6 @@@
  #include <linux/of_address.h>
  #include <linux/vexpress.h>
  
- #include <asm/hardware/sp810.h>
  static struct clk *vexpress_sp810_timerclken[4];
  static DEFINE_SPINLOCK(vexpress_sp810_lock);
  
@@@ -99,13 -98,19 +98,13 @@@ struct clk *vexpress_sp810_of_get(struc
        return vexpress_sp810_timerclken[clkspec->args[0]];
  }
  
 -static const __initconst struct of_device_id vexpress_fixed_clk_match[] = {
 -      { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
 -      { .compatible = "arm,vexpress-osc", .data = vexpress_osc_of_setup, },
 -      {}
 -};
 -
  void __init vexpress_clk_of_init(void)
  {
        struct device_node *node;
        struct clk *clk;
        struct clk *refclk, *timclk;
  
 -      of_clk_init(vexpress_fixed_clk_match);
 +      of_clk_init(NULL);
  
        node = of_find_compatible_node(NULL, NULL, "arm,sp810");
        vexpress_sp810_init(of_iomap(node, 0));
diff --combined drivers/cpufreq/Makefile
index 5399c45ac31100e2fd08dfa154a40429a2b141cd,030ba9534983b34bfed7152406f2f55249415ba0..863fd1865d45079c2db1f14780a6b205bc0f058a
@@@ -19,12 -19,11 +19,12 @@@ obj-$(CONFIG_GENERIC_CPUFREQ_CPU0) += c
  ##################################################################################
  # x86 drivers.
  # Link order matters. K8 is preferred to ACPI because of firmware bugs in early
 -# K8 systems. ACPI is preferred to all other hardware-specific drivers.
 +# K8 systems. This is still the case but acpi-cpufreq errors out so that
 +# powernow-k8 can load then. ACPI is preferred to all other hardware-specific drivers.
  # speedstep-* is preferred over p4-clockmod.
  
 -obj-$(CONFIG_X86_POWERNOW_K8)         += powernow-k8.o
  obj-$(CONFIG_X86_ACPI_CPUFREQ)                += acpi-cpufreq.o mperf.o
 +obj-$(CONFIG_X86_POWERNOW_K8)         += powernow-k8.o
  obj-$(CONFIG_X86_PCC_CPUFREQ)         += pcc-cpufreq.o
  obj-$(CONFIG_X86_POWERNOW_K6)         += powernow-k6.o
  obj-$(CONFIG_X86_POWERNOW_K7)         += powernow-k7.o
@@@ -40,11 -39,10 +40,11 @@@ obj-$(CONFIG_X86_SPEEDSTEP_SMI)            += spe
  obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO)  += speedstep-centrino.o
  obj-$(CONFIG_X86_P4_CLOCKMOD)         += p4-clockmod.o
  obj-$(CONFIG_X86_CPUFREQ_NFORCE2)     += cpufreq-nforce2.o
 +obj-$(CONFIG_X86_INTEL_PSTATE)                += intel_pstate.o
  
  ##################################################################################
  # ARM SoC drivers
- obj-$(CONFIG_UX500_SOC_DB8500)                += db8500-cpufreq.o
+ obj-$(CONFIG_UX500_SOC_DB8500)                += dbx500-cpufreq.o
  obj-$(CONFIG_ARM_S3C2416_CPUFREQ)     += s3c2416-cpufreq.o
  obj-$(CONFIG_ARM_S3C64XX_CPUFREQ)     += s3c64xx-cpufreq.o
  obj-$(CONFIG_ARM_S5PV210_CPUFREQ)     += s5pv210-cpufreq.o
@@@ -52,11 -50,8 +52,11 @@@ obj-$(CONFIG_ARM_EXYNOS_CPUFREQ)    += exy
  obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ)  += exynos4210-cpufreq.o
  obj-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ)  += exynos4x12-cpufreq.o
  obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ)  += exynos5250-cpufreq.o
 -obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)     += omap-cpufreq.o
 +obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ)    += kirkwood-cpufreq.o
 +obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)   += omap-cpufreq.o
  obj-$(CONFIG_ARM_SPEAR_CPUFREQ)               += spear-cpufreq.o
 +obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ)    += highbank-cpufreq.o
 +obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)               += imx6q-cpufreq.o
  
  ##################################################################################
  # PowerPC platform drivers
index 0000000000000000000000000000000000000000,9a623753dee234348bcdc5723eb9468adcecd4b5..72f0c3efa76e6b7d89114c463ccd7c5243ccb917
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,180 +1,174 @@@
 -#include <mach/id.h>
+ /*
+  * Copyright (C) STMicroelectronics 2009
+  * Copyright (C) ST-Ericsson SA 2010-2012
+  *
+  * License Terms: GNU General Public License v2
+  * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+  * Author: Martin Persson <martin.persson@stericsson.com>
+  * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+  */
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/cpufreq.h>
+ #include <linux/delay.h>
+ #include <linux/slab.h>
+ #include <linux/platform_device.h>
+ #include <linux/clk.h>
 -      cpumask_copy(policy->cpus, cpu_present_mask);
 -
 -      policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+ static struct cpufreq_frequency_table *freq_table;
+ static struct clk *armss_clk;
+ static struct freq_attr *dbx500_cpufreq_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+ };
+ static int dbx500_cpufreq_verify_speed(struct cpufreq_policy *policy)
+ {
+       return cpufreq_frequency_table_verify(policy, freq_table);
+ }
+ static int dbx500_cpufreq_target(struct cpufreq_policy *policy,
+                               unsigned int target_freq,
+                               unsigned int relation)
+ {
+       struct cpufreq_freqs freqs;
+       unsigned int idx;
+       int ret;
+       /* scale the target frequency to one of the extremes supported */
+       if (target_freq < policy->cpuinfo.min_freq)
+               target_freq = policy->cpuinfo.min_freq;
+       if (target_freq > policy->cpuinfo.max_freq)
+               target_freq = policy->cpuinfo.max_freq;
+       /* Lookup the next frequency */
+       if (cpufreq_frequency_table_target(policy, freq_table, target_freq,
+                                       relation, &idx))
+               return -EINVAL;
+       freqs.old = policy->cur;
+       freqs.new = freq_table[idx].frequency;
+       if (freqs.old == freqs.new)
+               return 0;
+       /* pre-change notification */
+       for_each_cpu(freqs.cpu, policy->cpus)
+               cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+       /* update armss clk frequency */
+       ret = clk_set_rate(armss_clk, freqs.new * 1000);
+       if (ret) {
+               pr_err("dbx500-cpufreq: Failed to set armss_clk to %d Hz: error %d\n",
+                      freqs.new * 1000, ret);
+               return ret;
+       }
+       /* post change notification */
+       for_each_cpu(freqs.cpu, policy->cpus)
+               cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+       return 0;
+ }
+ static unsigned int dbx500_cpufreq_getspeed(unsigned int cpu)
+ {
+       int i = 0;
+       unsigned long freq = clk_get_rate(armss_clk) / 1000;
+       while (freq_table[i].frequency != CPUFREQ_TABLE_END) {
+               if (freq <= freq_table[i].frequency)
+                       return freq_table[i].frequency;
+               i++;
+       }
+       /* We could not find a corresponding frequency. */
+       pr_err("dbx500-cpufreq: Failed to find cpufreq speed\n");
+       return 0;
+ }
+ static int __cpuinit dbx500_cpufreq_init(struct cpufreq_policy *policy)
+ {
+       int res;
+       /* get policy fields based on the table */
+       res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+       if (!res)
+               cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+       else {
+               pr_err("dbx500-cpufreq: Failed to read policy table\n");
+               return res;
+       }
+       policy->min = policy->cpuinfo.min_freq;
+       policy->max = policy->cpuinfo.max_freq;
+       policy->cur = dbx500_cpufreq_getspeed(policy->cpu);
+       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+       /*
+        * FIXME : Need to take time measurement across the target()
+        *         function with no/some/all drivers in the notification
+        *         list.
+        */
+       policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */
+       /* policy sharing between dual CPUs */
 -      if (!cpu_is_u8500_family())
 -              return -ENODEV;
 -
++      cpumask_setall(policy->cpus);
+       return 0;
+ }
+ static struct cpufreq_driver dbx500_cpufreq_driver = {
+       .flags  = CPUFREQ_STICKY | CPUFREQ_CONST_LOOPS,
+       .verify = dbx500_cpufreq_verify_speed,
+       .target = dbx500_cpufreq_target,
+       .get    = dbx500_cpufreq_getspeed,
+       .init   = dbx500_cpufreq_init,
+       .name   = "DBX500",
+       .attr   = dbx500_cpufreq_attr,
+ };
+ static int dbx500_cpufreq_probe(struct platform_device *pdev)
+ {
+       int i = 0;
+       freq_table = dev_get_platdata(&pdev->dev);
+       if (!freq_table) {
+               pr_err("dbx500-cpufreq: Failed to fetch cpufreq table\n");
+               return -ENODEV;
+       }
+       armss_clk = clk_get(&pdev->dev, "armss");
+       if (IS_ERR(armss_clk)) {
+               pr_err("dbx500-cpufreq: Failed to get armss clk\n");
+               return PTR_ERR(armss_clk);
+       }
+       pr_info("dbx500-cpufreq: Available frequencies:\n");
+       while (freq_table[i].frequency != CPUFREQ_TABLE_END) {
+               pr_info("  %d Mhz\n", freq_table[i].frequency/1000);
+               i++;
+       }
+       return cpufreq_register_driver(&dbx500_cpufreq_driver);
+ }
+ static struct platform_driver dbx500_cpufreq_plat_driver = {
+       .driver = {
+               .name = "cpufreq-ux500",
+               .owner = THIS_MODULE,
+       },
+       .probe = dbx500_cpufreq_probe,
+ };
+ static int __init dbx500_cpufreq_register(void)
+ {
+       return platform_driver_register(&dbx500_cpufreq_plat_driver);
+ }
+ device_initcall(dbx500_cpufreq_register);
+ MODULE_LICENSE("GPL v2");
+ MODULE_DESCRIPTION("cpufreq driver for DBX500");
index 1192518e1aca510637b8172562492bb2fee93d52,003a10eb12b6bce31ce21af0f93d096a9aacbf0b..a2bacf95b59ea543ca46104f9137a72497b89905
  #include <mach/hardware.h>
  #include <mach/irqs.h>
  #include <mach/db8500-regs.h>
 -#include <mach/id.h>
  #include "dbx500-prcmu-regs.h"
  
 -/* Offset for the firmware version within the TCPM */
 -#define PRCMU_FW_VERSION_OFFSET 0xA4
 -
  /* Index of different voltages to be used when accessing AVSData */
  #define PRCM_AVS_BASE         0x2FC
  #define PRCM_AVS_VBB_RET      (PRCM_AVS_BASE + 0x0)
  #define PRCM_REQ_MB5_I2C_HW_BITS      (PRCM_REQ_MB5 + 0x1)
  #define PRCM_REQ_MB5_I2C_REG          (PRCM_REQ_MB5 + 0x2)
  #define PRCM_REQ_MB5_I2C_VAL          (PRCM_REQ_MB5 + 0x3)
 -#define PRCMU_I2C_WRITE(slave) \
 -      (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0))
 -#define PRCMU_I2C_READ(slave) \
 -      (((slave) << 1) | BIT(0) | (cpu_is_u8500v2() ? BIT(6) : 0))
 +#define PRCMU_I2C_WRITE(slave) (((slave) << 1) | BIT(6))
 +#define PRCMU_I2C_READ(slave) (((slave) << 1) | BIT(0) | BIT(6))
  #define PRCMU_I2C_STOP_EN             BIT(3)
  
  /* Mailbox 5 ACKs */
@@@ -1043,13 -1049,12 +1043,13 @@@ int db8500_prcmu_get_ddr_opp(void
   *
   * This function sets the operating point of the DDR.
   */
 +static bool enable_set_ddr_opp;
  int db8500_prcmu_set_ddr_opp(u8 opp)
  {
        if (opp < DDR_100_OPP || opp > DDR_25_OPP)
                return -EINVAL;
        /* Changing the DDR OPP can hang the hardware pre-v21 */
 -      if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20())
 +      if (enable_set_ddr_opp)
                writeb(opp, PRCM_DDR_SUBSYS_APE_MINBW);
  
        return 0;
@@@ -2519,7 -2524,7 +2519,7 @@@ static bool read_mailbox_0(void
  
                for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) {
                        if (ev & prcmu_irq_bit[n])
 -                              generic_handle_irq(IRQ_PRCMU_BASE + n);
 +                              generic_handle_irq(irq_find_mapping(db8500_irq_domain, n));
                }
                r = true;
                break;
@@@ -2701,43 -2706,21 +2701,43 @@@ static struct irq_chip prcmu_irq_chip 
        .irq_unmask     = prcmu_irq_unmask,
  };
  
 -static char *fw_project_name(u8 project)
 +static __init char *fw_project_name(u32 project)
  {
        switch (project) {
        case PRCMU_FW_PROJECT_U8500:
                return "U8500";
 -      case PRCMU_FW_PROJECT_U8500_C2:
 -              return "U8500 C2";
 +      case PRCMU_FW_PROJECT_U8400:
 +              return "U8400";
        case PRCMU_FW_PROJECT_U9500:
                return "U9500";
 -      case PRCMU_FW_PROJECT_U9500_C2:
 -              return "U9500 C2";
 +      case PRCMU_FW_PROJECT_U8500_MBB:
 +              return "U8500 MBB";
 +      case PRCMU_FW_PROJECT_U8500_C1:
 +              return "U8500 C1";
 +      case PRCMU_FW_PROJECT_U8500_C2:
 +              return "U8500 C2";
 +      case PRCMU_FW_PROJECT_U8500_C3:
 +              return "U8500 C3";
 +      case PRCMU_FW_PROJECT_U8500_C4:
 +              return "U8500 C4";
 +      case PRCMU_FW_PROJECT_U9500_MBL:
 +              return "U9500 MBL";
 +      case PRCMU_FW_PROJECT_U8500_MBL:
 +              return "U8500 MBL";
 +      case PRCMU_FW_PROJECT_U8500_MBL2:
 +              return "U8500 MBL2";
        case PRCMU_FW_PROJECT_U8520:
 -              return "U8520";
 +              return "U8520 MBL";
        case PRCMU_FW_PROJECT_U8420:
                return "U8420";
 +      case PRCMU_FW_PROJECT_U9540:
 +              return "U9540";
 +      case PRCMU_FW_PROJECT_A9420:
 +              return "A9420";
 +      case PRCMU_FW_PROJECT_L8540:
 +              return "L8540";
 +      case PRCMU_FW_PROJECT_L8580:
 +              return "L8580";
        default:
                return "Unknown";
        }
@@@ -2754,14 -2737,13 +2754,14 @@@ static int db8500_irq_map(struct irq_do
  }
  
  static struct irq_domain_ops db8500_irq_ops = {
 -        .map    = db8500_irq_map,
 -        .xlate  = irq_domain_xlate_twocell,
 +      .map    = db8500_irq_map,
 +      .xlate  = irq_domain_xlate_twocell,
  };
  
  static int db8500_irq_init(struct device_node *np)
  {
 -      int irq_base = -1;
 +      int irq_base = 0;
 +      int i;
  
        /* In the device tree case, just take some IRQs */
        if (!np)
                return -ENOSYS;
        }
  
 +      /* All wakeups will be used, so create mappings for all */
 +      for (i = 0; i < NUM_PRCMU_WAKEUPS; i++)
 +              irq_create_mapping(db8500_irq_domain, i);
 +
        return 0;
  }
  
 -void __init db8500_prcmu_early_init(void)
 +static void dbx500_fw_version_init(struct platform_device *pdev,
 +                          u32 version_offset)
  {
 -      if (cpu_is_u8500v2() || cpu_is_u9540()) {
 -              void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);
 -
 -              if (tcpm_base != NULL) {
 -                      u32 version;
 -                      version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET);
 -                      fw_info.version.project = version & 0xFF;
 -                      fw_info.version.api_version = (version >> 8) & 0xFF;
 -                      fw_info.version.func_version = (version >> 16) & 0xFF;
 -                      fw_info.version.errata = (version >> 24) & 0xFF;
 -                      fw_info.valid = true;
 -                      pr_info("PRCMU firmware: %s, version %d.%d.%d\n",
 -                              fw_project_name(fw_info.version.project),
 -                              (version >> 8) & 0xFF, (version >> 16) & 0xFF,
 -                              (version >> 24) & 0xFF);
 -                      iounmap(tcpm_base);
 -              }
 +      struct resource *res;
 +      void __iomem *tcpm_base;
  
 -              if (cpu_is_u9540())
 -                      tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE,
 -                                              SZ_4K + SZ_8K) + SZ_8K;
 -              else
 -                      tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
 -      } else {
 -              pr_err("prcmu: Unsupported chip version\n");
 -              BUG();
 +      res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 +                                         "prcmu-tcpm");
 +      if (!res) {
 +              dev_err(&pdev->dev,
 +                      "Error: no prcmu tcpm memory region provided\n");
 +              return;
 +      }
 +      tcpm_base = ioremap(res->start, resource_size(res));
 +      if (tcpm_base != NULL) {
 +              u32 version;
 +
 +              version = readl(tcpm_base + version_offset);
 +              fw_info.version.project = (version & 0xFF);
 +              fw_info.version.api_version = (version >> 8) & 0xFF;
 +              fw_info.version.func_version = (version >> 16) & 0xFF;
 +              fw_info.version.errata = (version >> 24) & 0xFF;
 +              strncpy(fw_info.version.project_name,
 +                      fw_project_name(fw_info.version.project),
 +                      PRCMU_FW_PROJECT_NAME_LEN);
 +              fw_info.valid = true;
 +              pr_info("PRCMU firmware: %s(%d), version %d.%d.%d\n",
 +                      fw_info.version.project_name,
 +                      fw_info.version.project,
 +                      fw_info.version.api_version,
 +                      fw_info.version.func_version,
 +                      fw_info.version.errata);
 +              iounmap(tcpm_base);
        }
 +}
  
 +void __init db8500_prcmu_early_init(void)
 +{
        spin_lock_init(&mb0_transfer.lock);
        spin_lock_init(&mb0_transfer.dbb_irqs_lock);
        mutex_init(&mb0_transfer.ac_wake_lock);
@@@ -3102,8 -3072,8 +3102,8 @@@ static struct mfd_cell db8500_prcmu_dev
                .pdata_size = sizeof(db8500_regulators),
        },
        {
-               .name = "cpufreq-u8500",
-               .of_compatible = "stericsson,cpufreq-u8500",
+               .name = "cpufreq-ux500",
+               .of_compatible = "stericsson,cpufreq-ux500",
                .platform_data = &db8500_cpufreq_table,
                .pdata_size = sizeof(db8500_cpufreq_table),
        },
@@@ -3130,30 -3100,23 +3130,30 @@@ static void db8500_prcmu_update_cpufreq
   */
  static int db8500_prcmu_probe(struct platform_device *pdev)
  {
 -      struct ab8500_platform_data *ab8500_platdata = pdev->dev.platform_data;
        struct device_node *np = pdev->dev.of_node;
 +      struct prcmu_pdata *pdata = dev_get_platdata(&pdev->dev);
        int irq = 0, err = 0, i;
 -
 -      if (ux500_is_svp())
 -              return -ENODEV;
 +      struct resource *res;
  
        init_prcm_registers();
  
 +      dbx500_fw_version_init(pdev, pdata->version_offset);
 +      res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
 +      if (!res) {
 +              dev_err(&pdev->dev, "no prcmu tcdm region provided\n");
 +              return -ENOENT;
 +      }
 +      tcdm_base = devm_ioremap(&pdev->dev, res->start,
 +                      resource_size(res));
 +
        /* Clean up the mailbox interrupts after pre-kernel code. */
        writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
  
 -      if (np)
 -              irq = platform_get_irq(pdev, 0);
 -
 -      if (!np || irq <= 0)
 -              irq = IRQ_DB8500_PRCMU1;
 +      irq = platform_get_irq(pdev, 0);
 +      if (irq <= 0) {
 +              dev_err(&pdev->dev, "no prcmu irq provided\n");
 +              return -ENOENT;
 +      }
  
        err = request_threaded_irq(irq, prcmu_irq_handler,
                prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
  
        for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) {
                if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) {
 -                      db8500_prcmu_devs[i].platform_data = ab8500_platdata;
 +                      db8500_prcmu_devs[i].platform_data = pdata->ab_platdata;
                        db8500_prcmu_devs[i].pdata_size = sizeof(struct ab8500_platform_data);
                }
        }
  
 -      if (cpu_is_u8500v20_or_later())
 -              prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
 +      prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
  
        db8500_prcmu_update_cpufreq();