* mc13xxx-core, support for i2c, V4
From: Samuel Ortiz @ 2011-02-21 16:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201102122111.30525.marc@cpdesign.com.au>
Hi Mark,
On Sat, Feb 12, 2011 at 09:11:30PM +1100, Marc Reilly wrote:
> Hi Grant,
>
> Thanks for your comments,
>
> On Saturday, February 12, 2011 07:40:35 pm Grant Likely wrote:
> > On Tue, Jan 04, 2011 at 04:34:55PM +1100, Marc Reilly wrote:
> > > Hi,
> > >
> > > These patches add i2c support for the mc13xxx-core drive. For v4 I've
> > > tried to take in all previous comments, hopefully making it better to
> > > follow, and bisectable.
> >
> > This series looks okay to me. Since this is audio drivers, I expect
> > that it would best be taken via the ASoC tree? Have you sent it to
> > Mark Brown and the ALSA list for review?
> >
> > g.
>
> Actually only the mc13873 has audio support. I think these IC's really fit
> better under the MFD tree, but silly me didn't add Samuel Ortiz (MFD
> maintainer) to this series... so included him now.
>
> Samuel, are you the most appropriate to take this series in and would you like
> me to resend these patches to you? The thread archive is at [1].
Yes, I would be the one taking those patches. Please resend the patch set to
me, and I'll have a look. Has Uwe commented on them yet ?
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply
* [PATCH 0/3] OMAP2+ hwmod fixes
From: Paul Walmsley @ 2011-02-21 16:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D5E85EA.70605@ti.com>
Hello Beno?t, Rajendra,
On Fri, 18 Feb 2011, Cousson, Benoit wrote:
> On 2/16/2011 2:43 PM, Nayak, Rajendra wrote:
> > > -----Original Message-----
> > > From: Cousson, Benoit [mailto:b-cousson at ti.com]
> > > Sent: Wednesday, February 16, 2011 6:37 PM
> > > To: Nayak, Rajendra
> > > Cc: linux-omap at vger.kernel.org; paul at pwsan.com;
> > linux-arm-kernel at lists.infradead.org
> > > Subject: Re: [PATCH 0/3] OMAP2+ hwmod fixes
> > >
> > > Hi Rajendra,
> > >
> > > On 2/16/2011 1:11 PM, Nayak, Rajendra wrote:
> > > > This series fixes some hwmod api return values
> > > > and also adds some state checks.
> > > > The hwmod iterator functions are made to
> > > > continue and not break if one of the
> > > > callback functions ends up with an error.
> > >
> > > By doing that, you change the behavior of this function.
> > > I'm not sure I fully understand why.
> > > Could you elaborate on the use case?
> >
> > Since these functions iterate over all hwmods
> > calling a common callback function, there might
> > be cases wherein the callback function for *some*
> > hwmods might fail. For instance, if you run through
> > all hwmods and try to clear the context registers
> > for all of them, for some hwmods which might
> > not have context registers the callback function
> > might return a -EINVAL, however that should not
> > stop you from attempting to clear the context
> > registers for the rest of the hwmods which have
> > them and abort the function midway, no?
> > This is more hypothetical, however the real usecase
> > that prompted me with this patch was when I
> > had some wrong state check in _setup function,
> > and the iterator would stop with the first failure
> > and not even attempt to setup the rest of the
> > hwmods.
>
> Yeah, but by using that function you implicitly accept that an error will
> break the loop, so the function you pass to the iterator should be written for
> that. Meaning if you do not want to exit on error you should not report an
> error.
>
> > > To avoid that behavior in the past, I was just returning
> > > 0 in case of failure to avoid stopping the iteration.
> > > It looks like you do not want to stop the iteration but still
> > > retrieve the error.
> > > I do not see in this series what you plan to do with the
> > > error at the end of the iteration.
> >
> > Most users of these iterators would just use the non-zero
> > return value to throw an error/warning out stating there
> > were failures running through all the callback functions.
> > That does not change with this patch, and they can still
> > do it.
>
> Except that now, the iterator is not able anymore to stop on error if needed
> potentially.
> My point is that you are changing the behavior of this function without
> maintaining the legacy.
>
> So maybe creating a new iterator is a better approach.
> Even is this feature is not used today I have some secret plan for this
> behavior in the near future :-)
>
> But my initial comment is still valid, if you do not care about the final
> error status after the iteration, you'd better not return any error at the
> beginning.
> This was the behavior or the _setup until now.
The original behavior of the iterator was intentional: loops over
functions like _init_clocks() and _setup() should terminate upon
encountering an error. This is because the rest of that code currently
relies on the hwmod/clock data to be accurate in order to work. There is
no provision in the code for a hwmod to fail initialization due to data
errors. The idea was that if the data is inaccurate, the data should be
fixed first before doing anything else.
That said, I suppose that it's possible to enhance the code such that
hwmods could be allowed to fail initialization, and simply brick
themselves, rather than prevent the rest of the hwmods from initializing.
Probably that would need a new _HWMOD_STATE_INIT_FAILED, or something
similar. If a hwmod would end up in that state, it must not be used by
any other code, and the code should complain loudly.
The broader issue of whether the iterators should return immediately upon
failure (as the current code does), or continue through the rest of the
list, is a separate one. I'd suggest one of two approaches:
1. If the rest of the code can be changed to gracefully handle cases where
hwmod initialization fails, and if Beno?t agrees, I don't have a problem
with changing the iterator behavior to ignore failures as you describe.
Of course, all of the current users of omap_hwmod_for_each*() would need
to be checked to ensure that this behavior makes sense for them.
... or ...
2. The iterators could take an extra parameter that would control the
behavior upon encountering an error: terminate, or continue. But I am not
sure that both cases are needed. Ideas, feedback here are welcome.
- Paul
^ permalink raw reply
* [PATCH 2/2] Defines DA850/AM18xx/OMAPL1-38 SOC resources used by PRUSS UIO driver
From: Sergei Shtylyov @ 2011-02-21 17:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298041530-26855-3-git-send-email-pratheesh@ti.com>
Hello.
Pratheesh Gangadhar wrote:
> Signed-off-by: Pratheesh Gangadhar <pratheesh@ti.com>
Signoff should follow the change log, not precede it. "From:" line may
precede the change log.
> This patch defines PRUSS, ECAP clocks, memory and IRQ resources
> used by PRUSS UIO driver in DA850/AM18xx/OMAPL1-38 devices. UIO
> driver exports 64K I/O region of PRUSS, 128KB L3 RAM and 256KB
> DDR buffer to user space. PRUSS has 8 host event interrupt lines
> mapped to IRQ_DA8XX_EVTOUT0..7 of ARM9 INTC.These in conjunction
> with shared memory can be used to implement IPC between ARM9 and
> PRUSS.
> diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
> index 11f986b..ddcbac8 100644
> --- a/arch/arm/mach-davinci/board-da850-evm.c
> +++ b/arch/arm/mach-davinci/board-da850-evm.c
> @@ -1077,6 +1077,10 @@ static __init void da850_evm_init(void)
> pr_warning("da850_evm_init: i2c0 registration failed: %d\n",
> ret);
>
> + ret = da8xx_register_pruss();
> + if (ret)
> + pr_warning("da850_evm_init: pruss registration failed: %d\n",
> + ret);
>
> ret = da8xx_register_watchdog();
> if (ret)
I'd put this into a pacth of its own, to have the SoC level changes
separated from board-level changes...
> diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
> index 3443d97..0096d4f 100644
> --- a/arch/arm/mach-davinci/da850.c
> +++ b/arch/arm/mach-davinci/da850.c
> @@ -238,6 +238,13 @@ static struct clk tptc2_clk = {
> .flags = ALWAYS_ENABLED,
> };
>
> +static struct clk pruss_clk = {
> + .name = "pruss",
> + .parent = &pll0_sysclk2,
> + .lpsc = DA8XX_LPSC0_DMAX,
We have patch submitted by TI that renames this #define to DA8XX_LPSC0_PRUSS...
> + .flags = ALWAYS_ENABLED,
> +};
> +
We already have patch submitted by TI that defines this clock. It would be
nice if you coordinated your efforts to avoid such conflicts.
Again, I'd put the part adding the clocks into a patch of its own.
> diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
> index beda8a4..4ea3d1f 100644
> --- a/arch/arm/mach-davinci/devices-da8xx.c
> +++ b/arch/arm/mach-davinci/devices-da8xx.c
> @@ -725,3 +725,76 @@ int __init da8xx_register_cpuidle(void)
>
> return platform_device_register(&da8xx_cpuidle_device);
> }
> +static struct resource pruss_resources[] = {
> + [0] = {
> + .start = DA8XX_PRUSS_BASE,
> + .end = DA8XX_PRUSS_BASE + SZ_64K - 1,
> + .flags = IORESOURCE_MEM,
> + },
> + [1] = {
> + .start = DA8XX_L3RAM_BASE,
> + .end = DA8XX_L3RAM_BASE + SZ_128K - 1,
> + .flags = IORESOURCE_MEM,
Are you going to use all SRAM?
> + },
> + [2] = {
> + .start = 0,
> + .end = SZ_256K - 1,
> + .flags = IORESOURCE_MEM,
> + },
> +
> + [3] = {
> + .start = IRQ_DA8XX_EVTOUT0,
> + .end = IRQ_DA8XX_EVTOUT0,
> + .flags = IORESOURCE_IRQ,
> + },
> + [4] = {
> + .start = IRQ_DA8XX_EVTOUT1,
> + .end = IRQ_DA8XX_EVTOUT1,
> + .flags = IORESOURCE_IRQ,
> + },
> + [5] = {
> + .start = IRQ_DA8XX_EVTOUT2,
> + .end = IRQ_DA8XX_EVTOUT2,
> + .flags = IORESOURCE_IRQ,
> + },
> + [6] = {
> + .start = IRQ_DA8XX_EVTOUT3,
> + .end = IRQ_DA8XX_EVTOUT3,
> + .flags = IORESOURCE_IRQ,
> + },
> + [7] = {
> + .start = IRQ_DA8XX_EVTOUT4,
> + .end = IRQ_DA8XX_EVTOUT4,
> + .flags = IORESOURCE_IRQ,
> + },
> + [8] = {
> + .start = IRQ_DA8XX_EVTOUT5,
> + .end = IRQ_DA8XX_EVTOUT5,
> + .flags = IORESOURCE_IRQ,
> + },
> + [9] = {
> + .start = IRQ_DA8XX_EVTOUT6,
> + .end = IRQ_DA8XX_EVTOUT6,
> + .flags = IORESOURCE_IRQ,
> + },
> + [10] = {
> + .start = IRQ_DA8XX_EVTOUT7,
> + .end = IRQ_DA8XX_EVTOUT7,
> + .flags = IORESOURCE_IRQ,
> + },
> +};
> +
> +static struct platform_device pruss_device = {
> + .name = "pruss",
> + .id = 0,
> + .num_resources = ARRAY_SIZE(pruss_resources),
> + .resource = pruss_resources,
> + .dev = {
> + .coherent_dma_mask = 0xffffffff,
> + }
> +};
> +
> +int __init da8xx_register_pruss()
> +{
> + return platform_device_register(&pruss_device);
> +}
Again, there's TI patch that adds this device already...
WBR, Sergei
^ permalink raw reply
* [PATCH v3] dmaengine: mxs-dma: add dma support for i.MX23/28
From: Wolfram Sang @ 2011-02-21 17:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298283699-14635-1-git-send-email-shawn.guo@freescale.com>
On Mon, Feb 21, 2011 at 06:21:39PM +0800, Shawn Guo wrote:
> This patch adds dma support for Freescale MXS-based SoC i.MX23/28,
> including apbh-dma and apbx-dma.
>
> * apbh-dma and apbx-dma are supported in the driver as two mxs-dma
> instances.
>
> * apbh-dma is different between mx23 and mx28, hardware version
> register is used to differentiate.
>
> * mxs-dma supports pio function besides data transfer. The driver
> uses dma_data_direction DMA_NONE to identify the pio mode, and
> steals sgl and sg_len to get pio words and numbers from clients.
>
> * mxs dmaengine has some very specific features, like sense function
> and the special NAND support (nand_lock, nand_wait4ready). These
> are too specific to implemented in generic dmaengine driver.
>
> * The driver refers to imx-sdma and only a single descriptor is
> statically assigned to each channel.
>
> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110221/1990aa59/attachment.sig>
^ permalink raw reply
* [PATCH v3 0/2] Add dma device for i.MX23/28
From: Wolfram Sang @ 2011-02-21 17:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298284306-14710-1-git-send-email-shawn.guo@freescale.com>
On Mon, Feb 21, 2011 at 06:31:44PM +0800, Shawn Guo wrote:
> Hi Sascha,
>
> These two patches have no change since v2, and I re-post them to let
> you pick them up easily.
Both
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110221/86334d96/attachment.sig>
^ permalink raw reply
* [PATCH v2 0/2] Add PRUSS UIO driver support
From: Pratheesh Gangadhar @ 2011-02-21 17:35 UTC (permalink / raw)
To: linux-arm-kernel
This patch series add support for PRUSS (Programmable Real-time Unit Sub
System) UIO driver in Texas Instruments DA850, AM18xx and OMAPL1-38 processors.
PRUSS is programmable RISC core which can be used to implement Soft IPs
(eg:- DMA, CAN, UART,SmartCard) and Industrial communications data link layers
(eg:- PROFIBUS). UIO driver exposes PRUSS resources like memory and
interrupts to user space application.PRUSS UIO application API can be used
to control PRUs in PRUSS, setup PRU INTC, load firmware to PRUs and implement
IPC between Host processor and PRUs. More information on PRUSS and UIO linux
user space API available in the links below
http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit_Subsystem
http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader
http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader_API_Guide
Pratheesh Gangadhar (2):
PRUSS UIO driver support
Defines DA850/AM18xx/OMAPL1-38 SOC resources used by PRUSS UIO driver
arch/arm/mach-davinci/board-da850-evm.c | 4 +
arch/arm/mach-davinci/da850.c | 35 ++++
arch/arm/mach-davinci/devices-da8xx.c | 73 +++++++++
arch/arm/mach-davinci/include/mach/da8xx.h | 3 +
drivers/uio/Kconfig | 9 +
drivers/uio/Makefile | 1 +
drivers/uio/uio_pruss.c | 231 ++++++++++++++++++++++++++++
7 files changed, 356 insertions(+), 0 deletions(-)
create mode 100644 drivers/uio/uio_pruss.c
^ permalink raw reply
* [PATCH v2 1/2] PRUSS UIO driver support
From: Pratheesh Gangadhar @ 2011-02-21 17:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298309715-21362-1-git-send-email-pratheesh@ti.com>
This patch implements PRUSS (Programmable Real-time Unit Sub System)
UIO driver which exports SOC resources associated with PRUSS like
I/O, memories and IRQs to user space. PRUSS is dual 32-bit RISC
processors which is efficient in performing embedded tasks that
require manipulation of packed memory mapped data structures and
efficient in handling system events that have tight real time
constraints. This driver is currently supported on Texas Instruments
DA850, AM18xx and OMAPL1-38 devices.
For example, PRUSS runs firmware for real-time critical industrial
communication data link layer and communicates with application stack
running in user space via shared memory and IRQs.
Signed-off-by: Pratheesh Gangadhar <pratheesh@ti.com>
---
drivers/uio/Kconfig | 9 ++
drivers/uio/Makefile | 1 +
drivers/uio/uio_pruss.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 241 insertions(+), 0 deletions(-)
create mode 100644 drivers/uio/uio_pruss.c
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index bb44079..f92f20d 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -94,4 +94,13 @@ config UIO_NETX
To compile this driver as a module, choose M here; the module
will be called uio_netx.
+config UIO_PRUSS
+ tristate "Texas Instruments PRUSS driver"
+ depends on ARCH_DAVINCI_DA850
+ help
+ PRUSS driver for OMAPL138/DA850/AM18XX devices
+ PRUSS driver requires user space components
+ To compile this driver as a module, choose M here: the module
+ will be called uio_pruss.
+
endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 18fd818..d4dd9a5 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_UIO_AEC) += uio_aec.o
obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
obj-$(CONFIG_UIO_NETX) += uio_netx.o
+obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
new file mode 100644
index 0000000..b402197
--- /dev/null
+++ b/drivers/uio/uio_pruss.c
@@ -0,0 +1,231 @@
+/*
+ * Programmable Real-Time Unit Sub System (PRUSS) UIO driver (uio_pruss)
+ *
+ * This driver exports PRUSS host event out interrupts and PRUSS, L3 RAM,
+ * and DDR RAM to user space for applications interacting with PRUSS firmware
+ *
+ * Copyright (C) 2010-11 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/uio_driver.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#define DRV_NAME "pruss"
+#define DRV_VERSION "0.50"
+
+/*
+ * Host event IRQ numbers from PRUSS - PRUSS can generate upto 8 interrupt
+ * events to AINTC of ARM host processor - which can be used for IPC b/w PRUSS
+ * firmware and user space application, async notification from PRU firmware
+ * to user space application
+ * 3 PRU_EVTOUT0
+ * 4 PRU_EVTOUT1
+ * 5 PRU_EVTOUT2
+ * 6 PRU_EVTOUT3
+ * 7 PRU_EVTOUT4
+ * 8 PRU_EVTOUT5
+ * 9 PRU_EVTOUT6
+ * 10 PRU_EVTOUT7
+*/
+
+#define MAX_PRUSS_EVTOUT_INSTANCE 8
+
+#define PRUSS_INTC_HIPIR 0x4900
+#define PRUSS_INTC_HIPIR_INTPEND_MASK 0x80000000
+#define PRUSS_INTC_HIER 0x5500
+
+struct clk *pruss_clk;
+struct uio_info *info;
+void *ddr_virt_addr;
+dma_addr_t ddr_phy_addr;
+
+static irqreturn_t pruss_handler(int irq, struct uio_info *dev_info)
+{
+ void __iomem *int_enable_reg = dev_info->mem[0].internal_addr
+ + PRUSS_INTC_HIER;
+ void __iomem *int_status_reg = dev_info->mem[0].internal_addr
+ + PRUSS_INTC_HIPIR+((irq-1) << 2);
+ /* Is interrupt enabled and active ? */
+ if (!(ioread32(int_enable_reg) & (1<<(irq-1))) &&
+ (ioread32(int_status_reg) & PRUSS_INTC_HIPIR_INTPEND_MASK))
+ return IRQ_NONE;
+
+ /* Disable interrupt */
+ iowrite32(ioread32(int_enable_reg) & ~(1<<(irq-1)),
+ int_enable_reg);
+ return IRQ_HANDLED;
+}
+
+static void pruss_cleanup(struct platform_device *dev, struct uio_info *info)
+{
+ int count;
+ if (info) {
+ for (count = 0; count < MAX_PRUSS_EVTOUT_INSTANCE; count++) {
+ uio_unregister_device(&info[count]);
+ kfree(info[count].name);
+ iounmap(info[count].mem[0].internal_addr);
+
+ }
+ if (ddr_virt_addr)
+ dma_free_coherent(&dev->dev, info[0].mem[2].size,
+ info[0].mem[2].internal_addr,
+ info[0].mem[2].addr);
+ kfree(info);
+ }
+ if (pruss_clk != NULL)
+ clk_put(pruss_clk);
+}
+
+static int __devinit pruss_probe(struct platform_device *dev)
+{
+ int ret = -ENODEV, count = 0;
+ struct resource *regs_pruram, *regs_l3ram, *regs_ddr;
+ char *string;
+
+ /* Power on PRU in case its not done as part of boot-loader */
+ pruss_clk = clk_get(&dev->dev, "pruss");
+ if (IS_ERR(pruss_clk)) {
+ dev_err(&dev->dev, "Failed to get clock\n");
+ ret = PTR_ERR(pruss_clk);
+ return ret;
+ } else {
+ clk_enable(pruss_clk);
+ }
+
+ info = kzalloc(sizeof(struct uio_info) * MAX_PRUSS_EVTOUT_INSTANCE,
+ GFP_KERNEL);
+ if (info == NULL)
+ return -ENOMEM;
+
+ regs_pruram = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!regs_pruram) {
+ dev_err(&dev->dev, "No memory resource specified\n");
+ goto out_free;
+ }
+
+ regs_l3ram = platform_get_resource(dev, IORESOURCE_MEM, 1);
+ if (!regs_l3ram) {
+ dev_err(&dev->dev, "No memory resource specified\n");
+ goto out_free;
+ }
+
+ regs_ddr = platform_get_resource(dev, IORESOURCE_MEM, 2);
+ if (!regs_ddr) {
+ dev_err(&dev->dev, "No memory resource specified\n");
+ goto out_free;
+ }
+ ddr_virt_addr =
+ dma_alloc_coherent(&dev->dev, regs_ddr->end - regs_ddr->start + 1,
+ &ddr_phy_addr, GFP_KERNEL | GFP_DMA);
+ if (!ddr_virt_addr) {
+ dev_err(&dev->dev, "Could not allocate external memory\n");
+ goto out_free;
+ }
+
+ for (count = 0; count < MAX_PRUSS_EVTOUT_INSTANCE; count++) {
+ info[count].mem[0].addr = regs_pruram->start;
+ info[count].mem[0].size =
+ regs_pruram->end - regs_pruram->start + 1;
+ if (!info[count].mem[0].addr ||
+ !(info[count].mem[0].size - 1)) {
+ dev_err(&dev->dev, "Invalid memory resource\n");
+ goto out_free;
+ }
+ info[count].mem[0].internal_addr =
+ ioremap(regs_pruram->start, info[count].mem[0].size);
+ if (!info[count].mem[0].internal_addr) {
+ dev_err(&dev->dev,
+ "Can't remap memory address range\n");
+ goto out_free;
+ }
+ info[count].mem[0].memtype = UIO_MEM_PHYS;
+
+ info[count].mem[1].addr = regs_l3ram->start;
+ info[count].mem[1].size =
+ regs_l3ram->end - regs_l3ram->start + 1;
+ if (!info[count].mem[1].addr ||
+ !(info[count].mem[1].size - 1)) {
+ dev_err(&dev->dev, "Invalid memory resource\n");
+ goto out_free;
+ }
+ info[count].mem[1].memtype = UIO_MEM_PHYS;
+
+ info[count].mem[2].internal_addr = ddr_virt_addr;
+ info[count].mem[2].addr = ddr_phy_addr;
+ info[count].mem[2].size = regs_ddr->end - regs_ddr->start + 1;
+ info[count].mem[2].memtype = UIO_MEM_PHYS;
+
+ string = kzalloc(20, GFP_KERNEL);
+ sprintf(string, "pruss_evt%d", count);
+ info[count].name = string;
+ info[count].version = "0.50";
+
+ /* Register PRUSS IRQ lines */
+ info[count].irq = IRQ_DA8XX_EVTOUT0 + count;
+
+ info[count].irq_flags = 0;
+ info[count].handler = pruss_handler;
+
+ ret = uio_register_device(&dev->dev, &info[count]);
+
+ if (ret < 0)
+ goto out_free;
+ }
+
+ platform_set_drvdata(dev, info);
+ return 0;
+
+out_free:
+ pruss_cleanup(dev, info);
+ return ret;
+}
+
+static int __devexit pruss_remove(struct platform_device *dev)
+{
+ struct uio_info *info = platform_get_drvdata(dev);
+ pruss_cleanup(dev, info);
+ platform_set_drvdata(dev, NULL);
+ return 0;
+}
+
+static struct platform_driver pruss_driver = {
+ .probe = pruss_probe,
+ .remove = __devexit_p(pruss_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pruss_init_module(void)
+{
+ return platform_driver_register(&pruss_driver);
+}
+
+module_init(pruss_init_module);
+
+static void __exit pruss_exit_module(void)
+{
+ platform_driver_unregister(&pruss_driver);
+}
+
+module_exit(pruss_exit_module);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Amit Chatterjee <amit.chatterjee@ti.com>");
+MODULE_AUTHOR("Pratheesh Gangadhar <pratheesh@ti.com>");
--
1.6.0.6
^ permalink raw reply related
* [PATCH v2 2/2] Defines DA850/AM18xx/OMAPL1-38 SOC resources used by PRUSS UIO driver
From: Pratheesh Gangadhar @ 2011-02-21 17:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298309715-21362-2-git-send-email-pratheesh@ti.com>
This patch defines PRUSS, ECAP clocks, memory and IRQ resources
used by PRUSS UIO driver in DA850/AM18xx/OMAPL1-38 devices. UIO
driver exports 64K I/O region of PRUSS, 128KB L3 RAM and 256KB
DDR buffer to user space. PRUSS has 8 host event interrupt lines
mapped to IRQ_DA8XX_EVTOUT0..7 of ARM9 INTC.These in conjunction
with shared memory can be used to implement IPC between ARM9 and
PRUSS.
Signed-off-by: Pratheesh Gangadhar <pratheesh@ti.com>
---
arch/arm/mach-davinci/board-da850-evm.c | 4 ++
arch/arm/mach-davinci/da850.c | 35 +++++++++++++
arch/arm/mach-davinci/devices-da8xx.c | 73 ++++++++++++++++++++++++++++
arch/arm/mach-davinci/include/mach/da8xx.h | 3 +
4 files changed, 115 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 11f986b..bd85aa3 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1077,6 +1077,10 @@ static __init void da850_evm_init(void)
pr_warning("da850_evm_init: i2c0 registration failed: %d\n",
ret);
+ ret = da8xx_register_pruss();
+ if (ret)
+ pr_warning("da850_evm_init: pruss registration failed: %d\n",
+ ret);
ret = da8xx_register_watchdog();
if (ret)
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 3443d97..0096d4f 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -238,6 +238,13 @@ static struct clk tptc2_clk = {
.flags = ALWAYS_ENABLED,
};
+static struct clk pruss_clk = {
+ .name = "pruss",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA8XX_LPSC0_DMAX,
+ .flags = ALWAYS_ENABLED,
+};
+
static struct clk uart0_clk = {
.name = "uart0",
.parent = &pll0_sysclk2,
@@ -359,6 +366,30 @@ static struct clk usb20_clk = {
.gpsc = 1,
};
+static struct clk ecap0_clk = {
+ .name = "ecap0",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA8XX_LPSC1_ECAP,
+ .flags = DA850_CLK_ASYNC3,
+ .gpsc = 1,
+};
+
+static struct clk ecap1_clk = {
+ .name = "ecap1",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA8XX_LPSC1_ECAP,
+ .flags = DA850_CLK_ASYNC3,
+ .gpsc = 1,
+};
+
+static struct clk ecap2_clk = {
+ .name = "ecap2",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA8XX_LPSC1_ECAP,
+ .flags = DA850_CLK_ASYNC3,
+ .gpsc = 1,
+};
+
static struct clk_lookup da850_clks[] = {
CLK(NULL, "ref", &ref_clk),
CLK(NULL, "pll0", &pll0_clk),
@@ -386,6 +417,7 @@ static struct clk_lookup da850_clks[] = {
CLK(NULL, "tptc1", &tptc1_clk),
CLK(NULL, "tpcc1", &tpcc1_clk),
CLK(NULL, "tptc2", &tptc2_clk),
+ CLK(NULL, "pruss", &pruss_clk),
CLK(NULL, "uart0", &uart0_clk),
CLK(NULL, "uart1", &uart1_clk),
CLK(NULL, "uart2", &uart2_clk),
@@ -403,6 +435,9 @@ static struct clk_lookup da850_clks[] = {
CLK(NULL, "aemif", &aemif_clk),
CLK(NULL, "usb11", &usb11_clk),
CLK(NULL, "usb20", &usb20_clk),
+ CLK(NULL, "ecap0", &ecap0_clk),
+ CLK(NULL, "ecap1", &ecap1_clk),
+ CLK(NULL, "ecap2", &ecap2_clk),
CLK(NULL, NULL, NULL),
};
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index beda8a4..4ea3d1f 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -725,3 +725,76 @@ int __init da8xx_register_cpuidle(void)
return platform_device_register(&da8xx_cpuidle_device);
}
+static struct resource pruss_resources[] = {
+ [0] = {
+ .start = DA8XX_PRUSS_BASE,
+ .end = DA8XX_PRUSS_BASE + SZ_64K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DA8XX_L3RAM_BASE,
+ .end = DA8XX_L3RAM_BASE + SZ_128K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 0,
+ .end = SZ_256K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ [3] = {
+ .start = IRQ_DA8XX_EVTOUT0,
+ .end = IRQ_DA8XX_EVTOUT0,
+ .flags = IORESOURCE_IRQ,
+ },
+ [4] = {
+ .start = IRQ_DA8XX_EVTOUT1,
+ .end = IRQ_DA8XX_EVTOUT1,
+ .flags = IORESOURCE_IRQ,
+ },
+ [5] = {
+ .start = IRQ_DA8XX_EVTOUT2,
+ .end = IRQ_DA8XX_EVTOUT2,
+ .flags = IORESOURCE_IRQ,
+ },
+ [6] = {
+ .start = IRQ_DA8XX_EVTOUT3,
+ .end = IRQ_DA8XX_EVTOUT3,
+ .flags = IORESOURCE_IRQ,
+ },
+ [7] = {
+ .start = IRQ_DA8XX_EVTOUT4,
+ .end = IRQ_DA8XX_EVTOUT4,
+ .flags = IORESOURCE_IRQ,
+ },
+ [8] = {
+ .start = IRQ_DA8XX_EVTOUT5,
+ .end = IRQ_DA8XX_EVTOUT5,
+ .flags = IORESOURCE_IRQ,
+ },
+ [9] = {
+ .start = IRQ_DA8XX_EVTOUT6,
+ .end = IRQ_DA8XX_EVTOUT6,
+ .flags = IORESOURCE_IRQ,
+ },
+ [10] = {
+ .start = IRQ_DA8XX_EVTOUT7,
+ .end = IRQ_DA8XX_EVTOUT7,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device pruss_device = {
+ .name = "pruss",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(pruss_resources),
+ .resource = pruss_resources,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ }
+};
+
+int __init da8xx_register_pruss()
+{
+ return platform_device_register(&pruss_device);
+}
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index cfcb223..3ed6ee0 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -60,6 +60,7 @@ extern unsigned int da850_max_speed;
#define DA8XX_PLL0_BASE 0x01c11000
#define DA8XX_TIMER64P0_BASE 0x01c20000
#define DA8XX_TIMER64P1_BASE 0x01c21000
+#define DA8XX_PRUSS_BASE 0x01c30000
#define DA8XX_GPIO_BASE 0x01e26000
#define DA8XX_PSC1_BASE 0x01e27000
#define DA8XX_LCD_CNTRL_BASE 0x01e13000
@@ -68,6 +69,7 @@ extern unsigned int da850_max_speed;
#define DA8XX_AEMIF_CS2_BASE 0x60000000
#define DA8XX_AEMIF_CS3_BASE 0x62000000
#define DA8XX_AEMIF_CTL_BASE 0x68000000
+#define DA8XX_L3RAM_BASE 0x80000000
#define DA8XX_DDR2_CTL_BASE 0xb0000000
#define DA8XX_ARM_RAM_BASE 0xffff0000
@@ -90,6 +92,7 @@ int da850_register_cpufreq(char *async_clk);
int da8xx_register_cpuidle(void);
void __iomem * __init da8xx_get_mem_ctlr(void);
int da850_register_pm(struct platform_device *pdev);
+int da8xx_register_pruss(void);
extern struct platform_device da8xx_serial_device;
extern struct emac_platform_data da8xx_emac_pdata;
--
1.6.0.6
^ permalink raw reply related
* [PATCH v3] mmc: mxs-mmc: add mmc host driver for i.MX23/28
From: Wolfram Sang @ 2011-02-21 17:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298284528-14761-1-git-send-email-shawn.guo@freescale.com>
Shawn,
On Mon, Feb 21, 2011 at 06:35:28PM +0800, Shawn Guo wrote:
> This adds the mmc host driver for Freescale MXS-based SoC i.MX23/28.
> The driver calls into mxs-dma via generic dmaengine api for both pio
> and data transfer.
>
> Thanks Chris Ball for the indentation patch.
>
> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
What throughput rates do you get on a mx28-regulated slot serving a card
at 50Mhz? This is poor here (55kb/s) while it is OK at 25Mhz. Could be a
board issue though (or we can fix it later), rest works fine, thus:
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110221/8244f36f/attachment.sig>
^ permalink raw reply
* [PATCH v3] Add mmc device for i.MX23/28
From: Wolfram Sang @ 2011-02-21 17:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298284979-14853-1-git-send-email-shawn.guo@freescale.com>
On Mon, Feb 21, 2011 at 06:42:53PM +0800, Shawn Guo wrote:
> This patch set is to add mmc device for i.MX23 and i.MX28.
Patches 1-4
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110221/6ae2de27/attachment.sig>
^ permalink raw reply
* [PATCH v3 5/6] ARM: mxs/mx23evk: add mmc device
From: Wolfram Sang @ 2011-02-21 17:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298284979-14853-6-git-send-email-shawn.guo@freescale.com>
> +static struct mxs_mmc_platform_data mx23_mmc_pdata __initdata = {
Minor nit: Maybe mx23evk_mmc_pdata? (same for next patch)
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110221/dc4416a5/attachment.sig>
^ permalink raw reply
* OMAP4: IRQ line of CortexA9 performance monitor
From: Santosh Shilimkar @ 2011-02-21 17:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <yw1x62sd1f26.fsf@unicorn.mansr.com>
> -----Original Message-----
> From: linux-omap-owner at vger.kernel.org [mailto:linux-omap-
> owner at vger.kernel.org] On Behalf Of M?ns Rullg?rd
> Sent: Monday, February 21, 2011 10:49 PM
> To: linux-omap at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org
> Subject: Re: OMAP4: IRQ line of CortexA9 performance monitor
>
> Ming Lei <tom.leiming@gmail.com> writes:
>
> > Hi,
> >
> > From chapter 17 of "Interrupt controller", OMAP4 TRM, I can't
> > find what is the interrupt line of CortexA9 performance monitor
> > in omap4. Seems without this information, we can't use perf on
> > omap4.
> >
> > Any suggestions or ideas about it?
>
> The PMU interrupt is routed through the CTI, which needs to be
> properly
> configured. Unfortunately, the CTI is not documented in the public
> TRM,
> and nobody has seen fit to submit a patch suitable for upstream.
> Some dirty hacks have been posted, though.
>
Mans is right. Last time I looked at this, the OMAP4 PMU support
needed some hacky code and was not fitting to the generic PMU
framework.
I will take a second look at it and see if a patch can be generated
for upstream.
Regards,
Santosh
^ permalink raw reply
* [PATCH 1/3] OMAP: smartreflex: move plat/smartreflex.h to mach-omap2/smartreflex.h
From: Paul Walmsley @ 2011-02-21 18:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D6236AE.7000407@ti.com>
Hi Beno?t,
On Mon, 21 Feb 2011, Cousson, Benoit wrote:
> In fact that include is not used for OMAP4 data and does not seems to be used
> either in this file.
> I guess you can simply remove it.
Thanks, done. Updated patch below.
- Paul
From: Paul Walmsley <paul@pwsan.com>
Date: Wed, 16 Feb 2011 21:49:21 -0700
Subject: [PATCH] OMAP: smartreflex: move plat/smartreflex.h to mach-omap2/smartreflex.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
There's no reason for this header file to be in
plat-omap/include/plat/smartreflex.h. The hardware devices are in
OMAP2+ SoCs only. Leaving this header file in plat-omap causes
problems due to cross-dependencies with other header files that should
live in mach-omap2/.
Thanks to Beno?t Cousson <b-cousson@ti.com> for suggesting the removal
of the smartreflex.h include from the OMAP3xxx hwmod data.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Beno?t Cousson <b-cousson@ti.com>
---
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 1 -
arch/arm/mach-omap2/smartreflex-class3.c | 2 +-
arch/arm/mach-omap2/smartreflex.c | 2 +-
.../include/plat => mach-omap2}/smartreflex.h | 0
arch/arm/mach-omap2/sr_device.c | 2 +-
5 files changed, 3 insertions(+), 4 deletions(-)
rename arch/arm/{plat-omap/include/plat => mach-omap2}/smartreflex.h (100%)
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 8d81813..5445588 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -21,7 +21,6 @@
#include <plat/l4_3xxx.h>
#include <plat/i2c.h>
#include <plat/gpio.h>
-#include <plat/smartreflex.h>
#include "omap_hwmod_common_data.h"
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index 60e7055..f438cf4 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -11,7 +11,7 @@
* published by the Free Software Foundation.
*/
-#include <plat/smartreflex.h>
+#include "smartreflex.h"
static int sr_class3_enable(struct voltagedomain *voltdm)
{
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index c37e823..077dfb6 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -26,9 +26,9 @@
#include <linux/pm_runtime.h>
#include <plat/common.h>
-#include <plat/smartreflex.h>
#include "pm.h"
+#include "smartreflex.h"
#define SMARTREFLEX_NAME_LEN 16
#define NVALUE_NAME_LEN 40
diff --git a/arch/arm/plat-omap/include/plat/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
similarity index 100%
rename from arch/arm/plat-omap/include/plat/smartreflex.h
rename to arch/arm/mach-omap2/smartreflex.h
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index b1e0af1..a636604 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -23,9 +23,9 @@
#include <linux/io.h>
#include <plat/omap_device.h>
-#include <plat/smartreflex.h>
#include <plat/voltage.h>
+#include "smartreflex.h"
#include "control.h"
#include "pm.h"
--
1.7.2.3
^ permalink raw reply related
* [patch-v2.6.39 6/7] OMAP4430: hwmod data: Adding USBOTG
From: Tony Lindgren @ 2011-02-21 18:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D5EA36A.4000903@ti.com>
* Cousson, Benoit <b-cousson@ti.com> [110218 08:49]:
> ---
> From b2190f0d339c9d843eb5e370d0db8b7090fbcfab Mon Sep 17 00:00:00 2001
> From: Benoit Cousson <b-cousson@ti.com>
> Date: Fri, 18 Feb 2011 14:01:06 +0100
> Subject: [PATCH] OMAP4: hwmod data: Add rev and dev_attr fields in McSPI
>
> - Add a rev attribute to identify various McSPI IP version.
> - Add a dev_attr structure to provide the number of chipselect
> supported by the instance.
Looks like one seems to be wrapped and does not apply even after unwapping..
Tony
^ permalink raw reply
* [PATCH v3 2/2] OMAP: IOMMU: add support to callback during fault handling
From: Ramirez Luna, Omar @ 2011-02-21 18:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297884951-3019-3-git-send-email-dacohen@gmail.com>
Hi,
On Wed, Feb 16, 2011 at 1:35 PM, David Cohen <dacohen@gmail.com> wrote:
> diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
> index 49a1e5e..adb083e 100644
> --- a/arch/arm/mach-omap2/iommu2.c
> +++ b/arch/arm/mach-omap2/iommu2.c
...
>
> ? ? ? ?da = iommu_read_reg(obj, MMU_FAULT_AD);
> ? ? ? ?*ra = da;
>
> + ? ? ? if (stat & MMU_IRQ_TLBMISS)
> + ? ? ? ? ? ? ? errs |= OMAP_IOMMU_ERR_TLB_MISS;
> + ? ? ? if (stat & MMU_IRQ_TRANSLATIONFAULT)
> + ? ? ? ? ? ? ? errs |= OMAP_IOMMU_ERR_TRANS_FAULT;
> + ? ? ? if (stat & MMU_IRQ_EMUMISS)
> + ? ? ? ? ? ? ? errs |= OMAP_IOMMU_ERR_EMU_MISS;
> + ? ? ? if (stat & MMU_IRQ_TABLEWALKFAULT)
> + ? ? ? ? ? ? ? errs |= OMAP_IOMMU_ERR_TBLWALK_FAULT;
> + ? ? ? if (stat & MMU_IRQ_MULTIHITFAULT)
> + ? ? ? ? ? ? ? errs |= OMAP_IOMMU_ERR_MULTIHIT_FAULT;
I still don't think this adds any value, "generic layer" and omap
errors are the same thing in this case... OTOH OMAP 1710 (not
supported by iommu yet) has the following bits:
3 Prefetch_err
2 Perm_fault
1 Tlb_miss
0 Trans_fault
They don't match any of your "generic layer errors" masks for reading,
hence more generic errors will need to be defined, and then more OMAP#
masks... I think we just need to stick with the mach specific errors,
and let mach code handle its specifics when reporting.
But anyway it is just me...
> diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
> index f55f458..b0e0efc 100644
> --- a/arch/arm/plat-omap/iommu.c
> +++ b/arch/arm/plat-omap/iommu.c
> @@ -780,25 +780,19 @@ static void iopgtable_clear_entry_all(struct iommu *obj)
> ?*/
> ?static irqreturn_t iommu_fault_handler(int irq, void *data)
> ?{
> - ? ? ? u32 stat, da;
> + ? ? ? u32 da, errs;
> ? ? ? ?u32 *iopgd, *iopte;
> - ? ? ? int err = -EIO;
> ? ? ? ?struct iommu *obj = data;
>
> ? ? ? ?if (!obj->refcount)
> ? ? ? ? ? ? ? ?return IRQ_NONE;
>
> - ? ? ? /* Dynamic loading TLB or PTE */
> - ? ? ? if (obj->isr)
> - ? ? ? ? ? ? ? err = obj->isr(obj);
> -
> - ? ? ? if (!err)
> - ? ? ? ? ? ? ? return IRQ_HANDLED;
> -
> ? ? ? ?clk_enable(obj->clk);
> - ? ? ? stat = iommu_report_fault(obj, &da);
> + ? ? ? errs = iommu_report_fault(obj, &da);
> ? ? ? ?clk_disable(obj->clk);
> - ? ? ? if (!stat)
> +
> + ? ? ? /* Fault callback or TLB/PTE Dynamic loading */
> + ? ? ? if (obj->isr && !obj->isr(obj, da, errs, obj->isr_priv))
> ? ? ? ? ? ? ? ?return IRQ_HANDLED;
BTW, why not changing the name isr for cb, it is confusing since there
is another fault_isr called by mmu, AFAIK nobody uses obj->isr
> ? ? ? ?iommu_disable(obj);
> @@ -806,15 +800,16 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
> ? ? ? ?iopgd = iopgd_offset(obj, da);
>
> ? ? ? ?if (!iopgd_is_table(*iopgd)) {
> - ? ? ? ? ? ? ? dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", obj->name,
> - ? ? ? ? ? ? ? ? ? ? ? da, iopgd, *iopgd);
> + ? ? ? ? ? ? ? dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p "
> + ? ? ? ? ? ? ? ? ? ? ? "*pgd:px%08x\n", obj->name, errs, da, iopgd, *iopgd);
> ? ? ? ? ? ? ? ?return IRQ_NONE;
> ? ? ? ?}
>
> ? ? ? ?iopte = iopte_offset(iopgd, da);
>
> - ? ? ? dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
> - ? ? ? ? ? ? ? obj->name, da, iopgd, *iopgd, iopte, *iopte);
> + ? ? ? dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x "
> + ? ? ? ? ? ? ? "pte:0x%p *pte:0x%08x\n", obj->name, errs, da, iopgd, *iopgd,
> + ? ? ? ? ? ? ? iopte, *iopte);
>
> ? ? ? ?return IRQ_NONE;
> ?}
> @@ -917,6 +912,33 @@ void iommu_put(struct iommu *obj)
> ?}
> ?EXPORT_SYMBOL_GPL(iommu_put);
>
> +int iommu_set_isr(const char *name,
> + ? ? ? ? ? ? ? ? int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?void *priv),
> + ? ? ? ? ? ? ? ? void *isr_priv)
So I think the following will be bad practice:
mmu = iommu_get("iva2");
if (!IS_ERR(mmu))
mmu->isr = mmu_fault_callback;
Shall we think anything to prevent such mis-usage?
Regards,
Omar
^ permalink raw reply
* [PATCH v2 1/2] PRUSS UIO driver support
From: Hans J. Koch @ 2011-02-21 18:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298309715-21362-2-git-send-email-pratheesh@ti.com>
On Mon, Feb 21, 2011 at 11:05:14PM +0530, Pratheesh Gangadhar wrote:
> This patch implements PRUSS (Programmable Real-time Unit Sub System)
> UIO driver which exports SOC resources associated with PRUSS like
> I/O, memories and IRQs to user space. PRUSS is dual 32-bit RISC
> processors which is efficient in performing embedded tasks that
> require manipulation of packed memory mapped data structures and
> efficient in handling system events that have tight real time
> constraints. This driver is currently supported on Texas Instruments
> DA850, AM18xx and OMAPL1-38 devices.
> For example, PRUSS runs firmware for real-time critical industrial
> communication data link layer and communicates with application stack
> running in user space via shared memory and IRQs.
>
> Signed-off-by: Pratheesh Gangadhar <pratheesh@ti.com>
Looks much better now. Just some minor issues, see below.
Thanks,
Hans
> ---
> drivers/uio/Kconfig | 9 ++
> drivers/uio/Makefile | 1 +
> drivers/uio/uio_pruss.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 241 insertions(+), 0 deletions(-)
> create mode 100644 drivers/uio/uio_pruss.c
>
> diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
> index bb44079..f92f20d 100644
> --- a/drivers/uio/Kconfig
> +++ b/drivers/uio/Kconfig
> @@ -94,4 +94,13 @@ config UIO_NETX
> To compile this driver as a module, choose M here; the module
> will be called uio_netx.
>
> +config UIO_PRUSS
> + tristate "Texas Instruments PRUSS driver"
> + depends on ARCH_DAVINCI_DA850
> + help
> + PRUSS driver for OMAPL138/DA850/AM18XX devices
> + PRUSS driver requires user space components
It would be nice to mention a link here where these user space components are
available.
> + To compile this driver as a module, choose M here: the module
> + will be called uio_pruss.
> +
> endif
> diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
> index 18fd818..d4dd9a5 100644
> --- a/drivers/uio/Makefile
> +++ b/drivers/uio/Makefile
> @@ -6,3 +6,4 @@ obj-$(CONFIG_UIO_AEC) += uio_aec.o
> obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
> obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
> obj-$(CONFIG_UIO_NETX) += uio_netx.o
> +obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o
> diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
> new file mode 100644
> index 0000000..b402197
> --- /dev/null
> +++ b/drivers/uio/uio_pruss.c
> @@ -0,0 +1,231 @@
> +/*
> + * Programmable Real-Time Unit Sub System (PRUSS) UIO driver (uio_pruss)
> + *
> + * This driver exports PRUSS host event out interrupts and PRUSS, L3 RAM,
> + * and DDR RAM to user space for applications interacting with PRUSS firmware
> + *
> + * Copyright (C) 2010-11 Texas Instruments Incorporated - http://www.ti.com/
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation version 2.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
> + * kind, whether express or implied; without even the implied warranty
> + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/uio_driver.h>
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/slab.h>
> +
> +#define DRV_NAME "pruss"
> +#define DRV_VERSION "0.50"
> +
> +/*
> + * Host event IRQ numbers from PRUSS - PRUSS can generate upto 8 interrupt
> + * events to AINTC of ARM host processor - which can be used for IPC b/w PRUSS
> + * firmware and user space application, async notification from PRU firmware
> + * to user space application
> + * 3 PRU_EVTOUT0
> + * 4 PRU_EVTOUT1
> + * 5 PRU_EVTOUT2
> + * 6 PRU_EVTOUT3
> + * 7 PRU_EVTOUT4
> + * 8 PRU_EVTOUT5
> + * 9 PRU_EVTOUT6
> + * 10 PRU_EVTOUT7
> +*/
> +
> +#define MAX_PRUSS_EVTOUT_INSTANCE 8
> +
> +#define PRUSS_INTC_HIPIR 0x4900
> +#define PRUSS_INTC_HIPIR_INTPEND_MASK 0x80000000
> +#define PRUSS_INTC_HIER 0x5500
> +
> +struct clk *pruss_clk;
> +struct uio_info *info;
> +void *ddr_virt_addr;
> +dma_addr_t ddr_phy_addr;
> +
> +static irqreturn_t pruss_handler(int irq, struct uio_info *dev_info)
> +{
> + void __iomem *int_enable_reg = dev_info->mem[0].internal_addr
> + + PRUSS_INTC_HIER;
> + void __iomem *int_status_reg = dev_info->mem[0].internal_addr
> + + PRUSS_INTC_HIPIR+((irq-1) << 2);
Blank line between variable definitions and code, please.
> + /* Is interrupt enabled and active ? */
> + if (!(ioread32(int_enable_reg) & (1<<(irq-1))) &&
Hmm. I'd prefer blanks around operands, like (1 << (irq - 1))).
I won't be too picky about that, noticing that checkpatch.pl doesn't complain.
If you want to do me a favor, you can fix it ;-)
> + (ioread32(int_status_reg) & PRUSS_INTC_HIPIR_INTPEND_MASK))
> + return IRQ_NONE;
> +
> + /* Disable interrupt */
> + iowrite32(ioread32(int_enable_reg) & ~(1<<(irq-1)),
If you save the return value of the first ioread32(int_enable_reg) in a variable,
you don't need the second hardware access.
> + int_enable_reg);
> + return IRQ_HANDLED;
> +}
> +
> +static void pruss_cleanup(struct platform_device *dev, struct uio_info *info)
> +{
> + int count;
Blank line between variable definitions and code, please.
> + if (info) {
> + for (count = 0; count < MAX_PRUSS_EVTOUT_INSTANCE; count++) {
> + uio_unregister_device(&info[count]);
> + kfree(info[count].name);
> + iounmap(info[count].mem[0].internal_addr);
> +
> + }
> + if (ddr_virt_addr)
> + dma_free_coherent(&dev->dev, info[0].mem[2].size,
> + info[0].mem[2].internal_addr,
> + info[0].mem[2].addr);
> + kfree(info);
> + }
> + if (pruss_clk != NULL)
> + clk_put(pruss_clk);
> +}
> +
> +static int __devinit pruss_probe(struct platform_device *dev)
> +{
> + int ret = -ENODEV, count = 0;
> + struct resource *regs_pruram, *regs_l3ram, *regs_ddr;
> + char *string;
> +
> + /* Power on PRU in case its not done as part of boot-loader */
> + pruss_clk = clk_get(&dev->dev, "pruss");
> + if (IS_ERR(pruss_clk)) {
> + dev_err(&dev->dev, "Failed to get clock\n");
> + ret = PTR_ERR(pruss_clk);
> + return ret;
> + } else {
> + clk_enable(pruss_clk);
> + }
> +
> + info = kzalloc(sizeof(struct uio_info) * MAX_PRUSS_EVTOUT_INSTANCE,
> + GFP_KERNEL);
> + if (info == NULL)
if (!info) looks better.
> + return -ENOMEM;
> +
> + regs_pruram = platform_get_resource(dev, IORESOURCE_MEM, 0);
> + if (!regs_pruram) {
> + dev_err(&dev->dev, "No memory resource specified\n");
> + goto out_free;
> + }
> +
> + regs_l3ram = platform_get_resource(dev, IORESOURCE_MEM, 1);
> + if (!regs_l3ram) {
> + dev_err(&dev->dev, "No memory resource specified\n");
> + goto out_free;
> + }
> +
> + regs_ddr = platform_get_resource(dev, IORESOURCE_MEM, 2);
> + if (!regs_ddr) {
> + dev_err(&dev->dev, "No memory resource specified\n");
> + goto out_free;
> + }
> + ddr_virt_addr =
> + dma_alloc_coherent(&dev->dev, regs_ddr->end - regs_ddr->start + 1,
> + &ddr_phy_addr, GFP_KERNEL | GFP_DMA);
> + if (!ddr_virt_addr) {
> + dev_err(&dev->dev, "Could not allocate external memory\n");
> + goto out_free;
> + }
> +
> + for (count = 0; count < MAX_PRUSS_EVTOUT_INSTANCE; count++) {
> + info[count].mem[0].addr = regs_pruram->start;
> + info[count].mem[0].size =
> + regs_pruram->end - regs_pruram->start + 1;
> + if (!info[count].mem[0].addr ||
> + !(info[count].mem[0].size - 1)) {
> + dev_err(&dev->dev, "Invalid memory resource\n");
> + goto out_free;
> + }
> + info[count].mem[0].internal_addr =
> + ioremap(regs_pruram->start, info[count].mem[0].size);
> + if (!info[count].mem[0].internal_addr) {
> + dev_err(&dev->dev,
> + "Can't remap memory address range\n");
> + goto out_free;
> + }
> + info[count].mem[0].memtype = UIO_MEM_PHYS;
> +
> + info[count].mem[1].addr = regs_l3ram->start;
> + info[count].mem[1].size =
> + regs_l3ram->end - regs_l3ram->start + 1;
> + if (!info[count].mem[1].addr ||
> + !(info[count].mem[1].size - 1)) {
> + dev_err(&dev->dev, "Invalid memory resource\n");
> + goto out_free;
> + }
> + info[count].mem[1].memtype = UIO_MEM_PHYS;
> +
> + info[count].mem[2].internal_addr = ddr_virt_addr;
> + info[count].mem[2].addr = ddr_phy_addr;
> + info[count].mem[2].size = regs_ddr->end - regs_ddr->start + 1;
> + info[count].mem[2].memtype = UIO_MEM_PHYS;
> +
> + string = kzalloc(20, GFP_KERNEL);
> + sprintf(string, "pruss_evt%d", count);
> + info[count].name = string;
> + info[count].version = "0.50";
> +
> + /* Register PRUSS IRQ lines */
> + info[count].irq = IRQ_DA8XX_EVTOUT0 + count;
> +
> + info[count].irq_flags = 0;
> + info[count].handler = pruss_handler;
> +
> + ret = uio_register_device(&dev->dev, &info[count]);
> +
> + if (ret < 0)
> + goto out_free;
> + }
> +
> + platform_set_drvdata(dev, info);
> + return 0;
> +
> +out_free:
> + pruss_cleanup(dev, info);
> + return ret;
> +}
> +
> +static int __devexit pruss_remove(struct platform_device *dev)
> +{
> + struct uio_info *info = platform_get_drvdata(dev);
Blank line, please.
> + pruss_cleanup(dev, info);
> + platform_set_drvdata(dev, NULL);
> + return 0;
> +}
> +
> +static struct platform_driver pruss_driver = {
> + .probe = pruss_probe,
> + .remove = __devexit_p(pruss_remove),
> + .driver = {
> + .name = DRV_NAME,
> + .owner = THIS_MODULE,
> + },
> +};
> +
> +static int __init pruss_init_module(void)
> +{
> + return platform_driver_register(&pruss_driver);
> +}
> +
> +module_init(pruss_init_module);
> +
> +static void __exit pruss_exit_module(void)
> +{
> + platform_driver_unregister(&pruss_driver);
> +}
> +
> +module_exit(pruss_exit_module);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_VERSION(DRV_VERSION);
> +MODULE_AUTHOR("Amit Chatterjee <amit.chatterjee@ti.com>");
> +MODULE_AUTHOR("Pratheesh Gangadhar <pratheesh@ti.com>");
> --
> 1.6.0.6
>
>
^ permalink raw reply
* [PATCH 3/3] OMAP2+: voltage: reorganize, split code from data
From: Paul Walmsley @ 2011-02-21 18:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTikdx41hE5d5xG8rpB95DUvVu0=VHi6Zj=ePtREb@mail.gmail.com>
Hello
On Mon, 21 Feb 2011, Gulati, Shweta wrote:
> On Mon, Feb 21, 2011 at 7:38 AM, Paul Walmsley <paul@pwsan.com> wrote:
> > diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c
> > index 0486fce..3c7f0c0 100644
> > --- a/arch/arm/mach-omap2/opp3xxx_data.c
> > +++ b/arch/arm/mach-omap2/opp3xxx_data.c
...
> > +/* VDD2 */
> > +struct omap_volt_data omap36xx_vddcore_volt_data[] = {
> > + ? ? ? VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c),
> > + ? ? ? VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),
> > + ? ? ? VOLT_DATA_DEFINE(0, 0, 0, 0),
> > +};
> > +
> The definition of "VOLT_DATA_DEFINE" is there in voltage.h
> I think its better to move these Volt_data to voltagedomains files
> rather than in
> OPP layer files
opp*_data.c is currently where process/wafer/die-variable parameters go.
The struct omap_volt_data also consists mostly[1] of
process/wafer/die-variable parameters. So it made sense to group it
there.
In comparison, voltagedomains*_data.c files consist of
process/wafer/die-invariant data, such as register layouts, voltage domain
partitioning, etc. This is data that we don't expect to ever change over
the lifetime of a production design.
You are correct in that there seems to be little point leaving the
VOLT_DATA_DEFINE macro in voltage.h, so I have moved this to
omap_opp_data.h.
- Paul
1. The SCM register offsets in the struct omap_volt_data don't technically
belong in the process/wafer/die-variable parameters. It probably would
make sense to replace these with SCM OPP IDs, and then to create an
interface in the SCM code to fetch the SR data from the SCM, given an OPP
ID.
^ permalink raw reply
* [PATCH v2 1/2] PRUSS UIO driver support
From: Thomas Gleixner @ 2011-02-21 18:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298309715-21362-2-git-send-email-pratheesh@ti.com>
On Mon, 21 Feb 2011, Pratheesh Gangadhar wrote:
> +static irqreturn_t pruss_handler(int irq, struct uio_info *dev_info)
> +{
> + void __iomem *int_enable_reg = dev_info->mem[0].internal_addr
> + + PRUSS_INTC_HIER;
> + void __iomem *int_status_reg = dev_info->mem[0].internal_addr
> + + PRUSS_INTC_HIPIR+((irq-1) << 2);
void __iomem *base = dev_info->mem[0].internal_addr;
void __iomem *int_enable_reg = base + PRUSS_INTC_HIER;
....
Makes that readable.
> + /* Is interrupt enabled and active ? */
> + if (!(ioread32(int_enable_reg) & (1<<(irq-1))) &&
> + (ioread32(int_status_reg) & PRUSS_INTC_HIPIR_INTPEND_MASK))
> + return IRQ_NONE;
That returns when the interrupt is disabled _AND_ pending. It should
return when the interrupt is disabled _OR_ not pending.
> +
> + /* Disable interrupt */
> + iowrite32(ioread32(int_enable_reg) & ~(1<<(irq-1)),
> + int_enable_reg);
Chosing shorter variable names avoid those line breaks all over the
place.
> + return IRQ_HANDLED;
> +}
> +
> +static void pruss_cleanup(struct platform_device *dev, struct uio_info *info)
> +{
> + int count;
New line between variables and code please
> + if (info) {
This check is silly. pruss_probe() returns right away when it cannot
allocate info. pruss_remove() is never called when info == NULL
> + for (count = 0; count < MAX_PRUSS_EVTOUT_INSTANCE; count++) {
> + uio_unregister_device(&info[count]);
> + kfree(info[count].name);
> + iounmap(info[count].mem[0].internal_addr);
Why do you map/unmap the same physical address 8 times ????
> + }
> + if (ddr_virt_addr)
> + dma_free_coherent(&dev->dev, info[0].mem[2].size,
> + info[0].mem[2].internal_addr,
> + info[0].mem[2].addr);
> + kfree(info);
> + }
> + if (pruss_clk != NULL)
Silly check as well.
> + clk_put(pruss_clk);
> +}
> +
> +static int __devinit pruss_probe(struct platform_device *dev)
> +{
> + int ret = -ENODEV, count = 0;
> + struct resource *regs_pruram, *regs_l3ram, *regs_ddr;
> + char *string;
> +
> + /* Power on PRU in case its not done as part of boot-loader */
> + pruss_clk = clk_get(&dev->dev, "pruss");
> + if (IS_ERR(pruss_clk)) {
> + dev_err(&dev->dev, "Failed to get clock\n");
> + ret = PTR_ERR(pruss_clk);
> + return ret;
> + } else {
> + clk_enable(pruss_clk);
> + }
> +
> + info = kzalloc(sizeof(struct uio_info) * MAX_PRUSS_EVTOUT_INSTANCE,
> + GFP_KERNEL);
> + if (info == NULL)
if (!info)
> + return -ENOMEM;
Leaves the clock enabled
> + regs_pruram = platform_get_resource(dev, IORESOURCE_MEM, 0);
> + if (!regs_pruram) {
> + dev_err(&dev->dev, "No memory resource specified\n");
> + goto out_free;
> + }
> +
> + regs_l3ram = platform_get_resource(dev, IORESOURCE_MEM, 1);
> + if (!regs_l3ram) {
> + dev_err(&dev->dev, "No memory resource specified\n");
> + goto out_free;
> + }
> +
> + regs_ddr = platform_get_resource(dev, IORESOURCE_MEM, 2);
> + if (!regs_ddr) {
> + dev_err(&dev->dev, "No memory resource specified\n");
> + goto out_free;
> + }
> + ddr_virt_addr =
> + dma_alloc_coherent(&dev->dev, regs_ddr->end - regs_ddr->start + 1,
> + &ddr_phy_addr, GFP_KERNEL | GFP_DMA);
> + if (!ddr_virt_addr) {
> + dev_err(&dev->dev, "Could not allocate external memory\n");
> + goto out_free;
> + }
> +
> + for (count = 0; count < MAX_PRUSS_EVTOUT_INSTANCE; count++) {
Sigh. Can't you have a pointer struct uio_info *p and do the following.
for (cnt = 0; p = info; cnt < MAX_PRUSS_EVTOUT_INSTANCE; cnt++, p++) {
p->mem[0] ...
> + info[count].mem[0].addr = regs_pruram->start;
> + info[count].mem[0].size =
> + regs_pruram->end - regs_pruram->start + 1;
> + if (!info[count].mem[0].addr ||
> + !(info[count].mem[0].size - 1)) {
All you catch is size == 0. So with size == 1 it works ???
> + dev_err(&dev->dev, "Invalid memory resource\n");
> + goto out_free;
> + }
> + info[count].mem[0].internal_addr =
> + ioremap(regs_pruram->start, info[count].mem[0].size);
That's redundant to remap the same address 8 times. That and the check
above should be done before the loop and the result used in the loop.
> + if (!info[count].mem[0].internal_addr) {
> + dev_err(&dev->dev,
> + "Can't remap memory address range\n");
> + goto out_free;
> + }
> + info[count].mem[0].memtype = UIO_MEM_PHYS;
> +
> + info[count].mem[1].addr = regs_l3ram->start;
> + info[count].mem[1].size =
> + regs_l3ram->end - regs_l3ram->start + 1;
> + if (!info[count].mem[1].addr ||
> + !(info[count].mem[1].size - 1)) {
> + dev_err(&dev->dev, "Invalid memory resource\n");
> + goto out_free;
> + }
No need to check the same thing over and over.
> + info[count].mem[1].memtype = UIO_MEM_PHYS;
> +
> + info[count].mem[2].internal_addr = ddr_virt_addr;
> + info[count].mem[2].addr = ddr_phy_addr;
> + info[count].mem[2].size = regs_ddr->end - regs_ddr->start + 1;
> + info[count].mem[2].memtype = UIO_MEM_PHYS;
> +
> + string = kzalloc(20, GFP_KERNEL);
> + sprintf(string, "pruss_evt%d", count);
> + info[count].name = string;
kasprintf() please
> + info[count].version = "0.50";
> +
> + /* Register PRUSS IRQ lines */
> + info[count].irq = IRQ_DA8XX_EVTOUT0 + count;
> +
> + info[count].irq_flags = 0;
Is already zero
> + info[count].handler = pruss_handler;
> +
> + ret = uio_register_device(&dev->dev, &info[count]);
> +
> + if (ret < 0)
> + goto out_free;
> + }
> +
> + platform_set_drvdata(dev, info);
> + return 0;
> +
> +out_free:
> + pruss_cleanup(dev, info);
> + return ret;
> +}
> +
> +static int __devexit pruss_remove(struct platform_device *dev)
> +{
> + struct uio_info *info = platform_get_drvdata(dev);
Empty line between variables and code.
> + pruss_cleanup(dev, info);
> + platform_set_drvdata(dev, NULL);
> + return 0;
Thanks,
tglx
^ permalink raw reply
* [PATCH 3/3] OMAP2+: voltage: reorganize, split code from data
From: Paul Walmsley @ 2011-02-21 19:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110221020856.7598.34506.stgit@twilight.localdomain>
On Sun, 20 Feb 2011, Paul Walmsley wrote:
> This is a first pass at reorganizing mach-omap2/voltage.c:
Here is an updated version of this patch. The changes from the
original version are:
- an errant debugging pr_err() has been removed
- the omap_volt_data voltage macros have been moved to
the opp*_data.c files
- the VOLT_DATA_DEFINE macro has been moved to omap-opp-data.h
- Paul
From: Paul Walmsley <paul@pwsan.com>
Date: Wed, 16 Feb 2011 21:49:22 -0700
Subject: [PATCH] OMAP2+: voltage: reorganize, split code from data
This is a first pass at reorganizing mach-omap2/voltage.c:
- Separate almost all of the data from the code of mach-omap2/voltage.c.
The code remains in mach-omap2/voltage.c. The data goes into one
of several places, depending on what type of data it is:
- Silicon process/validation data: mach-omap2/opp*_data.c
- VC (Voltage Controller) data: mach-omap2/vc*_data.c
- VP (Voltage Processor) data: mach-omap2/vp*_data.c
- Voltage domain data: mach-omap2/voltagedomains*_data.c
The ultimate goal is for all this data to be autogenerated, the same
way we autogenerate the rest of our data.
- Separate VC and VP common data from VDD-specific VC and VP data.
- Separate common voltage.c code from SoC-specific code; reuse common code.
- Reorganize structures to avoid unnecessary memory loss due to unpacked
fields.
There is much left to be done. VC code and VP code should be separated out
into vc*.c and vp*.c files. Many fields in the existing structures are
superfluous, and should be removed. Some code in voltage.c seems to be
duplicated; that code should be moved into functions of its own. Proper
voltage domain code should be created, as was done with the powerdomain
and clockdomains, and powerdomains should reference voltagedomains.
Thanks to Shweta Gulati <shweta.gulati@ti.com> for comments.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Shweta Gulati <shweta.gulati@ti.com>
---
arch/arm/mach-omap2/Makefile | 20 +-
arch/arm/mach-omap2/omap_opp_data.h | 24 +
arch/arm/mach-omap2/opp3xxx_data.c | 66 ++-
arch/arm/mach-omap2/opp4xxx_data.c | 43 +-
arch/arm/mach-omap2/vc.h | 83 ++
arch/arm/mach-omap2/vc3xxx_data.c | 63 ++
arch/arm/mach-omap2/vc44xx_data.c | 72 ++
arch/arm/mach-omap2/voltage.c | 1015 +++++++------------------
arch/arm/mach-omap2/voltage.h | 89 ++-
arch/arm/mach-omap2/voltagedomains3xxx_data.c | 95 +++
arch/arm/mach-omap2/voltagedomains44xx_data.c | 102 +++
arch/arm/mach-omap2/vp.h | 143 ++++
arch/arm/mach-omap2/vp3xxx_data.c | 82 ++
arch/arm/mach-omap2/vp44xx_data.c | 97 +++
14 files changed, 1216 insertions(+), 778 deletions(-)
create mode 100644 arch/arm/mach-omap2/vc.h
create mode 100644 arch/arm/mach-omap2/vc3xxx_data.c
create mode 100644 arch/arm/mach-omap2/vc44xx_data.c
create mode 100644 arch/arm/mach-omap2/voltagedomains3xxx_data.c
create mode 100644 arch/arm/mach-omap2/voltagedomains44xx_data.c
create mode 100644 arch/arm/mach-omap2/vp.h
create mode 100644 arch/arm/mach-omap2/vp3xxx_data.c
create mode 100644 arch/arm/mach-omap2/vp44xx_data.c
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 1c0c2b0..d5c1dba 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -59,10 +59,10 @@ endif
# Power Management
ifeq ($(CONFIG_PM),y)
obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
-obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o voltage.o
-obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o voltage.o \
+obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o \
cpuidle34xx.o pm_bus.o
-obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o voltage.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o pm_bus.o
obj-$(CONFIG_PM_DEBUG) += pm-debug.o
obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o
obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o
@@ -78,13 +78,23 @@ endif
# PRCM
obj-$(CONFIG_ARCH_OMAP2) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
-obj-$(CONFIG_ARCH_OMAP3) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
+obj-$(CONFIG_ARCH_OMAP3) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \
+ vc3xxx_data.o vp3xxx_data.o
# XXX The presence of cm2xxx_3xxx.o on the line below is temporary and
# will be removed once the OMAP4 part of the codebase is converted to
# use OMAP4-specific PRCM functions.
obj-$(CONFIG_ARCH_OMAP4) += prcm.o cm2xxx_3xxx.o cminst44xx.o \
cm44xx.o prcm_mpu44xx.o \
- prminst44xx.o
+ prminst44xx.o vc44xx_data.o \
+ vp44xx_data.o
+
+# OMAP voltage domains
+voltagedomain-common := voltage.o
+obj-$(CONFIG_ARCH_OMAP2) += $(voltagedomain-common)
+obj-$(CONFIG_ARCH_OMAP3) += $(voltagedomain-common) \
+ voltagedomains3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP4) += $(voltagedomain-common) \
+ voltagedomains44xx_data.o
# OMAP powerdomain framework
powerdomain-common += powerdomain.o powerdomain-common.o
diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h
index 46ac27d..c784c12 100644
--- a/arch/arm/mach-omap2/omap_opp_data.h
+++ b/arch/arm/mach-omap2/omap_opp_data.h
@@ -21,6 +21,8 @@
#include <plat/omap_hwmod.h>
+#include "voltage.h"
+
/*
* *BIG FAT WARNING*:
* USE the following ONLY in opp data initialization common to an SoC.
@@ -65,8 +67,30 @@ struct omap_opp_def {
.u_volt = _uv, \
}
+/*
+ * Initialization wrapper used to define SmartReflex process data
+ * XXX Is this needed? Just use C99 initializers in data files?
+ */
+#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain) \
+{ \
+ .volt_nominal = _v_nom, \
+ .sr_efuse_offs = _efuse_offs, \
+ .sr_errminlimit = _errminlimit, \
+ .vp_errgain = _errgain \
+}
+
/* Use this to initialize the default table */
extern int __init omap_init_opp_table(struct omap_opp_def *opp_def,
u32 opp_def_size);
+
+extern struct omap_volt_data omap34xx_vddmpu_volt_data[];
+extern struct omap_volt_data omap34xx_vddcore_volt_data[];
+extern struct omap_volt_data omap36xx_vddmpu_volt_data[];
+extern struct omap_volt_data omap36xx_vddcore_volt_data[];
+
+extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[];
+extern struct omap_volt_data omap44xx_vdd_iva_volt_data[];
+extern struct omap_volt_data omap44xx_vdd_core_volt_data[];
+
#endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */
diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c
index 0486fce..3bba920 100644
--- a/arch/arm/mach-omap2/opp3xxx_data.c
+++ b/arch/arm/mach-omap2/opp3xxx_data.c
@@ -4,8 +4,9 @@
* Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
* Nishanth Menon
* Kevin Hilman
- * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2010-2011 Nokia Corporation.
* Eduardo Valentin
+ * Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -20,8 +21,71 @@
#include <plat/cpu.h>
+#include "control.h"
#include "omap_opp_data.h"
+/* 34xx */
+
+/* VDD1 */
+
+#define OMAP3430_VDD_MPU_OPP1_UV 975000
+#define OMAP3430_VDD_MPU_OPP2_UV 1075000
+#define OMAP3430_VDD_MPU_OPP3_UV 1200000
+#define OMAP3430_VDD_MPU_OPP4_UV 1270000
+#define OMAP3430_VDD_MPU_OPP5_UV 1350000
+
+struct omap_volt_data omap34xx_vddmpu_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* VDD2 */
+
+#define OMAP3430_VDD_CORE_OPP1_UV 975000
+#define OMAP3430_VDD_CORE_OPP2_UV 1050000
+#define OMAP3430_VDD_CORE_OPP3_UV 1150000
+
+struct omap_volt_data omap34xx_vddcore_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* 36xx */
+
+/* VDD1 */
+
+#define OMAP3630_VDD_MPU_OPP50_UV 1012500
+#define OMAP3630_VDD_MPU_OPP100_UV 1200000
+#define OMAP3630_VDD_MPU_OPP120_UV 1325000
+#define OMAP3630_VDD_MPU_OPP1G_UV 1375000
+
+struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23),
+ VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* VDD2 */
+
+#define OMAP3630_VDD_CORE_OPP50_UV 1000000
+#define OMAP3630_VDD_CORE_OPP100_UV 1200000
+
+struct omap_volt_data omap36xx_vddcore_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* OPP data */
+
static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
/* MPU OPP1 */
OPP_INITIALIZER("mpu", true, 125000000, 975000),
diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c
index a11fa56..fdee8d4 100644
--- a/arch/arm/mach-omap2/opp4xxx_data.c
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -5,8 +5,9 @@
* Nishanth Menon
* Kevin Hilman
* Thara Gopinath
- * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2010-2011 Nokia Corporation.
* Eduardo Valentin
+ * Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -21,8 +22,48 @@
#include <plat/cpu.h>
+#include "control.h"
#include "omap_opp_data.h"
+/*
+ * Structures containing OMAP4430 voltage supported and various
+ * voltage dependent data for each VDD.
+ */
+
+#define OMAP4430_VDD_MPU_OPP50_UV 930000
+#define OMAP4430_VDD_MPU_OPP100_UV 1100000
+#define OMAP4430_VDD_MPU_OPPTURBO_UV 1260000
+#define OMAP4430_VDD_MPU_OPPNITRO_UV 1350000
+
+struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
+ VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4430_VDD_IVA_OPP50_UV 930000
+#define OMAP4430_VDD_IVA_OPP100_UV 1100000
+#define OMAP4430_VDD_IVA_OPPTURBO_UV 1260000
+
+struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4430_VDD_CORE_OPP50_UV 930000
+#define OMAP4430_VDD_CORE_OPP100_UV 1100000
+
+struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+
static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
/* MPU OPP1 - OPP50 */
OPP_INITIALIZER("mpu", true, 300000000, 1100000),
diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h
new file mode 100644
index 0000000..e776777
--- /dev/null
+++ b/arch/arm/mach-omap2/vc.h
@@ -0,0 +1,83 @@
+/*
+ * OMAP3/4 Voltage Controller (VC) structure and macro definitions
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+#ifndef __ARCH_ARM_MACH_OMAP2_VC_H
+#define __ARCH_ARM_MACH_OMAP2_VC_H
+
+#include <linux/kernel.h>
+
+/**
+ * struct omap_vc_common_data - per-VC register/bitfield data
+ * @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register
+ * @valid: VALID bitmask in PRM_VC_BYPASS_VAL register
+ * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
+ * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
+ * @bypass_val_reg: Offset of PRM_VC_BYPASS_VAL reg from PRM start
+ * @data_shift: DATA field shift in PRM_VC_BYPASS_VAL register
+ * @slaveaddr_shift: SLAVEADDR field shift in PRM_VC_BYPASS_VAL register
+ * @regaddr_shift: REGADDR field shift in PRM_VC_BYPASS_VAL register
+ * @cmd_on_shift: ON field shift in PRM_VC_CMD_VAL_* register
+ * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register
+ * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register
+ * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register
+ *
+ * XXX One of cmd_on_mask and cmd_on_shift are not needed
+ * XXX VALID should probably be a shift, not a mask
+ */
+struct omap_vc_common_data {
+ u32 cmd_on_mask;
+ u32 valid;
+ u8 smps_sa_reg;
+ u8 smps_volra_reg;
+ u8 bypass_val_reg;
+ u8 data_shift;
+ u8 slaveaddr_shift;
+ u8 regaddr_shift;
+ u8 cmd_on_shift;
+ u8 cmd_onlp_shift;
+ u8 cmd_ret_shift;
+ u8 cmd_off_shift;
+};
+
+/**
+ * struct omap_vc_instance_data - VC per-instance data
+ * @vc_common: pointer to VC common data for this platform
+ * @smps_sa_mask: SA* bitmask in the PRM_VC_SMPS_SA register
+ * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
+ * @smps_sa_shift: SA* field shift in the PRM_VC_SMPS_SA register
+ * @smps_volra_shift: VOLRA* field shift in the PRM_VC_VOL_RA register
+ *
+ * XXX It is not necessary to have both a *_mask and a *_shift -
+ * remove one
+ */
+struct omap_vc_instance_data {
+ const struct omap_vc_common_data *vc_common;
+ u32 smps_sa_mask;
+ u32 smps_volra_mask;
+ u8 cmdval_reg;
+ u8 smps_sa_shift;
+ u8 smps_volra_shift;
+};
+
+extern struct omap_vc_instance_data omap3_vc1_data;
+extern struct omap_vc_instance_data omap3_vc2_data;
+
+extern struct omap_vc_instance_data omap4_vc_mpu_data;
+extern struct omap_vc_instance_data omap4_vc_iva_data;
+extern struct omap_vc_instance_data omap4_vc_core_data;
+
+#endif
+
diff --git a/arch/arm/mach-omap2/vc3xxx_data.c b/arch/arm/mach-omap2/vc3xxx_data.c
new file mode 100644
index 0000000..f37dc4b
--- /dev/null
+++ b/arch/arm/mach-omap2/vc3xxx_data.c
@@ -0,0 +1,63 @@
+/*
+ * OMAP3 Voltage Controller (VC) data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm-regbits-34xx.h"
+#include "voltage.h"
+
+#include "vc.h"
+
+/*
+ * VC data common to 34xx/36xx chips
+ * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
+ */
+static struct omap_vc_common_data omap3_vc_common = {
+ .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET,
+ .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+ .bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET,
+ .data_shift = OMAP3430_DATA_SHIFT,
+ .slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT,
+ .regaddr_shift = OMAP3430_REGADDR_SHIFT,
+ .valid = OMAP3430_VALID_MASK,
+ .cmd_on_shift = OMAP3430_VC_CMD_ON_SHIFT,
+ .cmd_on_mask = OMAP3430_VC_CMD_ON_MASK,
+ .cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT,
+ .cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT,
+ .cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT,
+};
+
+struct omap_vc_instance_data omap3_vc1_data = {
+ .vc_common = &omap3_vc_common,
+ .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET,
+ .smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
+ .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK,
+ .smps_volra_shift = OMAP3430_VOLRA0_SHIFT,
+ .smps_volra_mask = OMAP3430_VOLRA0_MASK,
+};
+
+struct omap_vc_instance_data omap3_vc2_data = {
+ .vc_common = &omap3_vc_common,
+ .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET,
+ .smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
+ .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK,
+ .smps_volra_shift = OMAP3430_VOLRA1_SHIFT,
+ .smps_volra_mask = OMAP3430_VOLRA1_MASK,
+};
diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c
new file mode 100644
index 0000000..548cb06
--- /dev/null
+++ b/arch/arm/mach-omap2/vc44xx_data.c
@@ -0,0 +1,72 @@
+/*
+ * OMAP4 Voltage Controller (VC) data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm44xx.h"
+#include "prm-regbits-44xx.h"
+#include "voltage.h"
+
+#include "vc.h"
+
+/*
+ * VC data common to 44xx chips
+ * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
+ */
+static const struct omap_vc_common_data omap4_vc_data = {
+ .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+ .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+ .bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET,
+ .data_shift = OMAP4430_DATA_SHIFT,
+ .slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT,
+ .regaddr_shift = OMAP4430_REGADDR_SHIFT,
+ .valid = OMAP4430_VALID_MASK,
+ .cmd_on_shift = OMAP4430_ON_SHIFT,
+ .cmd_on_mask = OMAP4430_ON_MASK,
+ .cmd_onlp_shift = OMAP4430_ONLP_SHIFT,
+ .cmd_ret_shift = OMAP4430_RET_SHIFT,
+ .cmd_off_shift = OMAP4430_OFF_SHIFT,
+};
+
+/* VC instance data for each controllable voltage line */
+struct omap_vc_instance_data omap4_vc_mpu_data = {
+ .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET,
+ .smps_sa_shift = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT,
+ .smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK,
+ .smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT,
+ .smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK,
+};
+
+struct omap_vc_instance_data omap4_vc_iva_data = {
+ .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET,
+ .smps_sa_shift = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT,
+ .smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK,
+ .smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT,
+ .smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK,
+};
+
+struct omap_vc_instance_data omap4_vc_core_data = {
+ .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET,
+ .smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT,
+ .smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK,
+ .smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT,
+ .smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK,
+};
+
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 3c9bcdc..e0cbd93 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -7,8 +7,9 @@
* Rajendra Nayak <rnayak@ti.com>
* Lesly A M <x0080970@ti.com>
*
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2008, 2011 Nokia Corporation
* Kalle Jokiniemi
+ * Paul Walmsley
*
* Copyright (C) 2010 Texas Instruments, Inc.
* Thara Gopinath <thara@ti.com>
@@ -36,284 +37,28 @@
#include "voltage.h"
-#define VP_IDLE_TIMEOUT 200
-#define VP_TRANXDONE_TIMEOUT 300
+#include "vc.h"
+#include "vp.h"
+
#define VOLTAGE_DIR_SIZE 16
-/* Voltage processor register offsets */
-struct vp_reg_offs {
- u8 vpconfig;
- u8 vstepmin;
- u8 vstepmax;
- u8 vlimitto;
- u8 vstatus;
- u8 voltage;
-};
-
-/* Voltage Processor bit field values, shifts and masks */
-struct vp_reg_val {
- /* PRM module */
- u16 prm_mod;
- /* VPx_VPCONFIG */
- u32 vpconfig_erroroffset;
- u16 vpconfig_errorgain;
- u32 vpconfig_errorgain_mask;
- u8 vpconfig_errorgain_shift;
- u32 vpconfig_initvoltage_mask;
- u8 vpconfig_initvoltage_shift;
- u32 vpconfig_timeouten;
- u32 vpconfig_initvdd;
- u32 vpconfig_forceupdate;
- u32 vpconfig_vpenable;
- /* VPx_VSTEPMIN */
- u8 vstepmin_stepmin;
- u16 vstepmin_smpswaittimemin;
- u8 vstepmin_stepmin_shift;
- u8 vstepmin_smpswaittimemin_shift;
- /* VPx_VSTEPMAX */
- u8 vstepmax_stepmax;
- u16 vstepmax_smpswaittimemax;
- u8 vstepmax_stepmax_shift;
- u8 vstepmax_smpswaittimemax_shift;
- /* VPx_VLIMITTO */
- u8 vlimitto_vddmin;
- u8 vlimitto_vddmax;
- u16 vlimitto_timeout;
- u8 vlimitto_vddmin_shift;
- u8 vlimitto_vddmax_shift;
- u8 vlimitto_timeout_shift;
- /* PRM_IRQSTATUS*/
- u32 tranxdone_status;
-};
-
-/* Voltage controller registers and offsets */
-struct vc_reg_info {
- /* PRM module */
- u16 prm_mod;
- /* VC register offsets */
- u8 smps_sa_reg;
- u8 smps_volra_reg;
- u8 bypass_val_reg;
- u8 cmdval_reg;
- u8 voltsetup_reg;
- /*VC_SMPS_SA*/
- u8 smps_sa_shift;
- u32 smps_sa_mask;
- /* VC_SMPS_VOL_RA */
- u8 smps_volra_shift;
- u32 smps_volra_mask;
- /* VC_BYPASS_VAL */
- u8 data_shift;
- u8 slaveaddr_shift;
- u8 regaddr_shift;
- u32 valid;
- /* VC_CMD_VAL */
- u8 cmd_on_shift;
- u8 cmd_onlp_shift;
- u8 cmd_ret_shift;
- u8 cmd_off_shift;
- u32 cmd_on_mask;
- /* PRM_VOLTSETUP */
- u8 voltsetup_shift;
- u32 voltsetup_mask;
-};
-/**
- * omap_vdd_info - Per Voltage Domain info
- *
- * @volt_data : voltage table having the distinct voltages supported
- * by the domain and other associated per voltage data.
- * @pmic_info : pmic specific parameters which should be populted by
- * the pmic drivers.
- * @vp_offs : structure containing the offsets for various
- * vp registers
- * @vp_reg : the register values, shifts, masks for various
- * vp registers
- * @vc_reg : structure containing various various vc registers,
- * shifts, masks etc.
- * @voltdm : pointer to the voltage domain structure
- * @debug_dir : debug directory for this voltage domain.
- * @curr_volt : current voltage for this vdd.
- * @ocp_mod : The prm module for accessing the prm irqstatus reg.
- * @prm_irqst_reg : prm irqstatus register.
- * @vp_enabled : flag to keep track of whether vp is enabled or not
- * @volt_scale : API to scale the voltage of the vdd.
- */
-struct omap_vdd_info {
- struct omap_volt_data *volt_data;
- struct omap_volt_pmic_info *pmic_info;
- struct vp_reg_offs vp_offs;
- struct vp_reg_val vp_reg;
- struct vc_reg_info vc_reg;
- struct voltagedomain voltdm;
- struct dentry *debug_dir;
- u32 curr_volt;
- u16 ocp_mod;
- u8 prm_irqst_reg;
- bool vp_enabled;
- u32 (*read_reg) (u16 mod, u8 offset);
- void (*write_reg) (u32 val, u16 mod, u8 offset);
- int (*volt_scale) (struct omap_vdd_info *vdd,
- unsigned long target_volt);
-};
-
-static struct omap_vdd_info *vdd_info;
+static struct omap_vdd_info **vdd_info;
+
/*
* Number of scalable voltage domains.
*/
static int nr_scalable_vdd;
-/* OMAP3 VDD sturctures */
-static struct omap_vdd_info omap3_vdd_info[] = {
- {
- .vp_offs = {
- .vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET,
- .vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
- .vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
- .vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET,
- .vstatus = OMAP3_PRM_VP1_STATUS_OFFSET,
- .voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET,
- },
- .voltdm = {
- .name = "mpu",
- },
- },
- {
- .vp_offs = {
- .vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET,
- .vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
- .vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
- .vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET,
- .vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
- .voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
- },
- .voltdm = {
- .name = "core",
- },
- },
-};
-
-#define OMAP3_NR_SCALABLE_VDD ARRAY_SIZE(omap3_vdd_info)
-
-/* OMAP4 VDD sturctures */
-static struct omap_vdd_info omap4_vdd_info[] = {
- {
- .vp_offs = {
- .vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET,
- .vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET,
- .vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET,
- .vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET,
- .vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET,
- .voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET,
- },
- .voltdm = {
- .name = "mpu",
- },
- },
- {
- .vp_offs = {
- .vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET,
- .vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET,
- .vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET,
- .vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET,
- .vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET,
- .voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET,
- },
- .voltdm = {
- .name = "iva",
- },
- },
- {
- .vp_offs = {
- .vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET,
- .vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET,
- .vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET,
- .vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET,
- .vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
- .voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
- },
- .voltdm = {
- .name = "core",
- },
- },
-};
-
-#define OMAP4_NR_SCALABLE_VDD ARRAY_SIZE(omap4_vdd_info)
-
-/*
- * Structures containing OMAP3430/OMAP3630 voltage supported and various
- * voltage dependent data for each VDD.
- */
-#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain) \
-{ \
- .volt_nominal = _v_nom, \
- .sr_efuse_offs = _efuse_offs, \
- .sr_errminlimit = _errminlimit, \
- .vp_errgain = _errgain \
-}
-
-/* VDD1 */
-static struct omap_volt_data omap34xx_vddmpu_volt_data[] = {
- VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18),
- VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18),
- VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-static struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
- VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16),
- VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23),
- VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-/* VDD2 */
-static struct omap_volt_data omap34xx_vddcore_volt_data[] = {
- VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-static struct omap_volt_data omap36xx_vddcore_volt_data[] = {
- VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-/*
- * Structures containing OMAP4430 voltage supported and various
- * voltage dependent data for each VDD.
- */
-static struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
- VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
- VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
- VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-static struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
- VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
- VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-static struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
- VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
+/* XXX document */
+static s16 prm_mod_offs;
+static s16 prm_irqst_ocp_mod_offs;
static struct dentry *voltage_dir;
/* Init function pointers */
-static void (*vc_init) (struct omap_vdd_info *vdd);
-static int (*vdd_data_configure) (struct omap_vdd_info *vdd);
+static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
+ unsigned long target_volt);
static u32 omap3_voltage_read_reg(u16 mod, u8 offset)
{
@@ -336,6 +81,60 @@ static void omap4_voltage_write_reg(u32 val, u16 mod, u8 offset)
omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, mod, offset);
}
+static int __init _config_common_vdd_data(struct omap_vdd_info *vdd)
+{
+ char *sys_ck_name;
+ struct clk *sys_ck;
+ u32 sys_clk_speed, timeout_val, waittime;
+
+ /*
+ * XXX Clockfw should handle this, or this should be in a
+ * struct record
+ */
+ if (cpu_is_omap24xx() || cpu_is_omap34xx())
+ sys_ck_name = "sys_ck";
+ else if (cpu_is_omap44xx())
+ sys_ck_name = "sys_clkin_ck";
+
+ /*
+ * Sys clk rate is require to calculate vp timeout value and
+ * smpswaittimemin and smpswaittimemax.
+ */
+ sys_ck = clk_get(NULL, sys_ck_name);
+ if (IS_ERR(sys_ck)) {
+ pr_warning("%s: Could not get the sys clk to calculate"
+ "various vdd_%s params\n", __func__, vdd->voltdm.name);
+ return -EINVAL;
+ }
+ sys_clk_speed = clk_get_rate(sys_ck);
+ clk_put(sys_ck);
+ /* Divide to avoid overflow */
+ sys_clk_speed /= 1000;
+
+ /* Generic voltage parameters */
+ vdd->curr_volt = 1200000;
+ vdd->volt_scale = vp_forceupdate_scale_voltage;
+ vdd->vp_enabled = false;
+
+ vdd->vp_rt_data.vpconfig_erroroffset =
+ (vdd->pmic_info->vp_erroroffset <<
+ vdd->vp_data->vp_common->vpconfig_erroroffset_shift);
+
+ timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
+ vdd->vp_rt_data.vlimitto_timeout = timeout_val;
+ vdd->vp_rt_data.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
+ vdd->vp_rt_data.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
+
+ waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
+ sys_clk_speed) / 1000;
+ vdd->vp_rt_data.vstepmin_smpswaittimemin = waittime;
+ vdd->vp_rt_data.vstepmax_smpswaittimemax = waittime;
+ vdd->vp_rt_data.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
+ vdd->vp_rt_data.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
+
+ return 0;
+}
+
/* Voltage debugfs support */
static int vp_volt_debug_get(void *data, u64 *val)
{
@@ -347,7 +146,7 @@ static int vp_volt_debug_get(void *data, u64 *val)
return -EINVAL;
}
- vsel = vdd->read_reg(vdd->vp_reg.prm_mod, vdd->vp_offs.voltage);
+ vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
pr_notice("curr_vsel = %x\n", vsel);
if (!vdd->pmic_info->vsel_to_uv) {
@@ -380,7 +179,6 @@ DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL,
static void vp_latch_vsel(struct omap_vdd_info *vdd)
{
u32 vpconfig;
- u16 mod;
unsigned long uvdc;
char vsel;
@@ -397,30 +195,27 @@ static void vp_latch_vsel(struct omap_vdd_info *vdd)
return;
}
- mod = vdd->vp_reg.prm_mod;
-
vsel = vdd->pmic_info->uv_to_vsel(uvdc);
- vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
- vpconfig &= ~(vdd->vp_reg.vpconfig_initvoltage_mask |
- vdd->vp_reg.vpconfig_initvdd);
- vpconfig |= vsel << vdd->vp_reg.vpconfig_initvoltage_shift;
+ vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
+ vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvoltage_mask |
+ vdd->vp_data->vp_common->vpconfig_initvdd);
+ vpconfig |= vsel << vdd->vp_data->vp_common->vpconfig_initvoltage_shift;
- vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+ vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
/* Trigger initVDD value copy to voltage processor */
- vdd->write_reg((vpconfig | vdd->vp_reg.vpconfig_initvdd), mod,
- vdd->vp_offs.vpconfig);
+ vdd->write_reg((vpconfig | vdd->vp_data->vp_common->vpconfig_initvdd),
+ prm_mod_offs, vdd->vp_data->vpconfig);
/* Clear initVDD copy trigger bit */
- vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+ vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
}
/* Generic voltage init functions */
static void __init vp_init(struct omap_vdd_info *vdd)
{
u32 vp_val;
- u16 mod;
if (!vdd->read_reg || !vdd->write_reg) {
pr_err("%s: No read/write API for accessing vdd_%s regs\n",
@@ -428,33 +223,31 @@ static void __init vp_init(struct omap_vdd_info *vdd)
return;
}
- mod = vdd->vp_reg.prm_mod;
-
- vp_val = vdd->vp_reg.vpconfig_erroroffset |
- (vdd->vp_reg.vpconfig_errorgain <<
- vdd->vp_reg.vpconfig_errorgain_shift) |
- vdd->vp_reg.vpconfig_timeouten;
- vdd->write_reg(vp_val, mod, vdd->vp_offs.vpconfig);
-
- vp_val = ((vdd->vp_reg.vstepmin_smpswaittimemin <<
- vdd->vp_reg.vstepmin_smpswaittimemin_shift) |
- (vdd->vp_reg.vstepmin_stepmin <<
- vdd->vp_reg.vstepmin_stepmin_shift));
- vdd->write_reg(vp_val, mod, vdd->vp_offs.vstepmin);
-
- vp_val = ((vdd->vp_reg.vstepmax_smpswaittimemax <<
- vdd->vp_reg.vstepmax_smpswaittimemax_shift) |
- (vdd->vp_reg.vstepmax_stepmax <<
- vdd->vp_reg.vstepmax_stepmax_shift));
- vdd->write_reg(vp_val, mod, vdd->vp_offs.vstepmax);
-
- vp_val = ((vdd->vp_reg.vlimitto_vddmax <<
- vdd->vp_reg.vlimitto_vddmax_shift) |
- (vdd->vp_reg.vlimitto_vddmin <<
- vdd->vp_reg.vlimitto_vddmin_shift) |
- (vdd->vp_reg.vlimitto_timeout <<
- vdd->vp_reg.vlimitto_timeout_shift));
- vdd->write_reg(vp_val, mod, vdd->vp_offs.vlimitto);
+ vp_val = vdd->vp_rt_data.vpconfig_erroroffset |
+ (vdd->vp_rt_data.vpconfig_errorgain <<
+ vdd->vp_data->vp_common->vpconfig_errorgain_shift) |
+ vdd->vp_data->vp_common->vpconfig_timeouten;
+ vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vpconfig);
+
+ vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin <<
+ vdd->vp_data->vp_common->vstepmin_smpswaittimemin_shift) |
+ (vdd->vp_rt_data.vstepmin_stepmin <<
+ vdd->vp_data->vp_common->vstepmin_stepmin_shift));
+ vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmin);
+
+ vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax <<
+ vdd->vp_data->vp_common->vstepmax_smpswaittimemax_shift) |
+ (vdd->vp_rt_data.vstepmax_stepmax <<
+ vdd->vp_data->vp_common->vstepmax_stepmax_shift));
+ vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmax);
+
+ vp_val = ((vdd->vp_rt_data.vlimitto_vddmax <<
+ vdd->vp_data->vp_common->vlimitto_vddmax_shift) |
+ (vdd->vp_rt_data.vlimitto_vddmin <<
+ vdd->vp_data->vp_common->vlimitto_vddmin_shift) |
+ (vdd->vp_rt_data.vlimitto_timeout <<
+ vdd->vp_data->vp_common->vlimitto_timeout_shift));
+ vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vlimitto);
}
static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
@@ -481,23 +274,23 @@ static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
}
(void) debugfs_create_x16("vp_errorgain", S_IRUGO, vdd->debug_dir,
- &(vdd->vp_reg.vpconfig_errorgain));
+ &(vdd->vp_rt_data.vpconfig_errorgain));
(void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO,
vdd->debug_dir,
- &(vdd->vp_reg.vstepmin_smpswaittimemin));
+ &(vdd->vp_rt_data.vstepmin_smpswaittimemin));
(void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir,
- &(vdd->vp_reg.vstepmin_stepmin));
+ &(vdd->vp_rt_data.vstepmin_stepmin));
(void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO,
vdd->debug_dir,
- &(vdd->vp_reg.vstepmax_smpswaittimemax));
+ &(vdd->vp_rt_data.vstepmax_smpswaittimemax));
(void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir,
- &(vdd->vp_reg.vstepmax_stepmax));
+ &(vdd->vp_rt_data.vstepmax_stepmax));
(void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir,
- &(vdd->vp_reg.vlimitto_vddmax));
+ &(vdd->vp_rt_data.vlimitto_vddmax));
(void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir,
- &(vdd->vp_reg.vlimitto_vddmin));
+ &(vdd->vp_rt_data.vlimitto_vddmin));
(void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir,
- &(vdd->vp_reg.vlimitto_timeout));
+ &(vdd->vp_rt_data.vlimitto_timeout));
(void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd->debug_dir,
(void *) vdd, &vp_volt_debug_fops);
(void) debugfs_create_file("curr_nominal_volt", S_IRUGO,
@@ -510,8 +303,12 @@ static int _pre_volt_scale(struct omap_vdd_info *vdd,
unsigned long target_volt, u8 *target_vsel, u8 *current_vsel)
{
struct omap_volt_data *volt_data;
+ const struct omap_vc_common_data *vc_common;
+ const struct omap_vp_common_data *vp_common;
u32 vc_cmdval, vp_errgain_val;
- u16 vp_mod, vc_mod;
+
+ vc_common = vdd->vc_data->vc_common;
+ vp_common = vdd->vp_data->vp_common;
/* Check if suffiecient pmic info is available for this vdd */
if (!vdd->pmic_info) {
@@ -533,33 +330,30 @@ static int _pre_volt_scale(struct omap_vdd_info *vdd,
return -EINVAL;
}
- vp_mod = vdd->vp_reg.prm_mod;
- vc_mod = vdd->vc_reg.prm_mod;
-
/* Get volt_data corresponding to target_volt */
volt_data = omap_voltage_get_voltdata(&vdd->voltdm, target_volt);
if (IS_ERR(volt_data))
volt_data = NULL;
*target_vsel = vdd->pmic_info->uv_to_vsel(target_volt);
- *current_vsel = vdd->read_reg(vp_mod, vdd->vp_offs.voltage);
+ *current_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
/* Setting the ON voltage to the new target voltage */
- vc_cmdval = vdd->read_reg(vc_mod, vdd->vc_reg.cmdval_reg);
- vc_cmdval &= ~vdd->vc_reg.cmd_on_mask;
- vc_cmdval |= (*target_vsel << vdd->vc_reg.cmd_on_shift);
- vdd->write_reg(vc_cmdval, vc_mod, vdd->vc_reg.cmdval_reg);
+ vc_cmdval = vdd->read_reg(prm_mod_offs, vdd->vc_data->cmdval_reg);
+ vc_cmdval &= ~vc_common->cmd_on_mask;
+ vc_cmdval |= (*target_vsel << vc_common->cmd_on_shift);
+ vdd->write_reg(vc_cmdval, prm_mod_offs, vdd->vc_data->cmdval_reg);
/* Setting vp errorgain based on the voltage */
if (volt_data) {
- vp_errgain_val = vdd->read_reg(vp_mod,
- vdd->vp_offs.vpconfig);
- vdd->vp_reg.vpconfig_errorgain = volt_data->vp_errgain;
- vp_errgain_val &= ~vdd->vp_reg.vpconfig_errorgain_mask;
- vp_errgain_val |= vdd->vp_reg.vpconfig_errorgain <<
- vdd->vp_reg.vpconfig_errorgain_shift;
- vdd->write_reg(vp_errgain_val, vp_mod,
- vdd->vp_offs.vpconfig);
+ vp_errgain_val = vdd->read_reg(prm_mod_offs,
+ vdd->vp_data->vpconfig);
+ vdd->vp_rt_data.vpconfig_errorgain = volt_data->vp_errgain;
+ vp_errgain_val &= ~vp_common->vpconfig_errorgain_mask;
+ vp_errgain_val |= vdd->vp_rt_data.vpconfig_errorgain <<
+ vp_common->vpconfig_errorgain_shift;
+ vdd->write_reg(vp_errgain_val, prm_mod_offs,
+ vdd->vp_data->vpconfig);
}
return 0;
@@ -585,7 +379,6 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
{
u32 loop_cnt = 0, retries_cnt = 0;
u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
- u16 mod;
u8 target_vsel, current_vsel;
int ret;
@@ -593,20 +386,19 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
if (ret)
return ret;
- mod = vdd->vc_reg.prm_mod;
-
- vc_valid = vdd->vc_reg.valid;
- vc_bypass_val_reg = vdd->vc_reg.bypass_val_reg;
- vc_bypass_value = (target_vsel << vdd->vc_reg.data_shift) |
+ vc_valid = vdd->vc_data->vc_common->valid;
+ vc_bypass_val_reg = vdd->vc_data->vc_common->bypass_val_reg;
+ vc_bypass_value = (target_vsel << vdd->vc_data->vc_common->data_shift) |
(vdd->pmic_info->pmic_reg <<
- vdd->vc_reg.regaddr_shift) |
+ vdd->vc_data->vc_common->regaddr_shift) |
(vdd->pmic_info->i2c_slave_addr <<
- vdd->vc_reg.slaveaddr_shift);
+ vdd->vc_data->vc_common->slaveaddr_shift);
- vdd->write_reg(vc_bypass_value, mod, vc_bypass_val_reg);
- vdd->write_reg(vc_bypass_value | vc_valid, mod, vc_bypass_val_reg);
+ vdd->write_reg(vc_bypass_value, prm_mod_offs, vc_bypass_val_reg);
+ vdd->write_reg(vc_bypass_value | vc_valid, prm_mod_offs,
+ vc_bypass_val_reg);
- vc_bypass_value = vdd->read_reg(mod, vc_bypass_val_reg);
+ vc_bypass_value = vdd->read_reg(prm_mod_offs, vc_bypass_val_reg);
/*
* Loop till the bypass command is acknowledged from the SMPS.
* NOTE: This is legacy code. The loop count and retry count needs
@@ -625,7 +417,8 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
loop_cnt = 0;
udelay(10);
}
- vc_bypass_value = vdd->read_reg(mod, vc_bypass_val_reg);
+ vc_bypass_value = vdd->read_reg(prm_mod_offs,
+ vc_bypass_val_reg);
}
_post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
@@ -637,7 +430,6 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
unsigned long target_volt)
{
u32 vpconfig;
- u16 mod, ocp_mod;
u8 target_vsel, current_vsel, prm_irqst_reg;
int ret, timeout = 0;
@@ -645,20 +437,18 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
if (ret)
return ret;
- mod = vdd->vp_reg.prm_mod;
- ocp_mod = vdd->ocp_mod;
- prm_irqst_reg = vdd->prm_irqst_reg;
+ prm_irqst_reg = vdd->vp_data->prm_irqst_data->prm_irqst_reg;
/*
* Clear all pending TransactionDone interrupt/status. Typical latency
* is <3us
*/
while (timeout++ < VP_TRANXDONE_TIMEOUT) {
- vdd->write_reg(vdd->vp_reg.tranxdone_status,
- ocp_mod, prm_irqst_reg);
- if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) &
- vdd->vp_reg.tranxdone_status))
- break;
+ vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
+ prm_irqst_ocp_mod_offs, prm_irqst_reg);
+ if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
+ vdd->vp_data->prm_irqst_data->tranxdone_status))
+ break;
udelay(1);
}
if (timeout >= VP_TRANXDONE_TIMEOUT) {
@@ -668,30 +458,30 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
}
/* Configure for VP-Force Update */
- vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
- vpconfig &= ~(vdd->vp_reg.vpconfig_initvdd |
- vdd->vp_reg.vpconfig_forceupdate |
- vdd->vp_reg.vpconfig_initvoltage_mask);
+ vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
+ vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvdd |
+ vdd->vp_data->vp_common->vpconfig_forceupdate |
+ vdd->vp_data->vp_common->vpconfig_initvoltage_mask);
vpconfig |= ((target_vsel <<
- vdd->vp_reg.vpconfig_initvoltage_shift));
- vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+ vdd->vp_data->vp_common->vpconfig_initvoltage_shift));
+ vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
/* Trigger initVDD value copy to voltage processor */
- vpconfig |= vdd->vp_reg.vpconfig_initvdd;
- vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+ vpconfig |= vdd->vp_data->vp_common->vpconfig_initvdd;
+ vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
/* Force update of voltage */
- vpconfig |= vdd->vp_reg.vpconfig_forceupdate;
- vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+ vpconfig |= vdd->vp_data->vp_common->vpconfig_forceupdate;
+ vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
/*
* Wait for TransactionDone. Typical latency is <200us.
* Depends on SMPSWAITTIMEMIN/MAX and voltage change
*/
timeout = 0;
- omap_test_timeout((vdd->read_reg(ocp_mod, prm_irqst_reg) &
- vdd->vp_reg.tranxdone_status),
- VP_TRANXDONE_TIMEOUT, timeout);
+ omap_test_timeout((vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
+ vdd->vp_data->prm_irqst_data->tranxdone_status),
+ VP_TRANXDONE_TIMEOUT, timeout);
if (timeout >= VP_TRANXDONE_TIMEOUT)
pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
"TRANXDONE never got set after the voltage update\n",
@@ -705,11 +495,11 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
*/
timeout = 0;
while (timeout++ < VP_TRANXDONE_TIMEOUT) {
- vdd->write_reg(vdd->vp_reg.tranxdone_status,
- ocp_mod, prm_irqst_reg);
- if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) &
- vdd->vp_reg.tranxdone_status))
- break;
+ vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
+ prm_irqst_ocp_mod_offs, prm_irqst_reg);
+ if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
+ vdd->vp_data->prm_irqst_data->tranxdone_status))
+ break;
udelay(1);
}
@@ -718,222 +508,95 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
"to clear the TRANXDONE status\n",
__func__, vdd->voltdm.name);
- vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
+ vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
/* Clear initVDD copy trigger bit */
- vpconfig &= ~vdd->vp_reg.vpconfig_initvdd;;
- vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+ vpconfig &= ~vdd->vp_data->vp_common->vpconfig_initvdd;
+ vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
/* Clear force bit */
- vpconfig &= ~vdd->vp_reg.vpconfig_forceupdate;
- vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+ vpconfig &= ~vdd->vp_data->vp_common->vpconfig_forceupdate;
+ vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
return 0;
}
-/* OMAP3 specific voltage init functions */
+static void __init omap3_vfsm_init(struct omap_vdd_info *vdd)
+{
+ /*
+ * Voltage Manager FSM parameters init
+ * XXX This data should be passed in from the board file
+ */
+ vdd->write_reg(OMAP3_CLKSETUP, prm_mod_offs, OMAP3_PRM_CLKSETUP_OFFSET);
+ vdd->write_reg(OMAP3_VOLTOFFSET, prm_mod_offs,
+ OMAP3_PRM_VOLTOFFSET_OFFSET);
+ vdd->write_reg(OMAP3_VOLTSETUP2, prm_mod_offs,
+ OMAP3_PRM_VOLTSETUP2_OFFSET);
+}
-/*
- * Intializes the voltage controller registers with the PMIC and board
- * specific parameters and voltage setup times for OMAP3.
- */
static void __init omap3_vc_init(struct omap_vdd_info *vdd)
{
- u32 vc_val;
- u16 mod;
- u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
static bool is_initialized;
+ u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
+ u32 vc_val;
- if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
- pr_err("%s: PMIC info requried to configure vc for"
- "vdd_%s not populated.Hence cannot initialize vc\n",
- __func__, vdd->voltdm.name);
- return;
- }
-
- if (!vdd->read_reg || !vdd->write_reg) {
- pr_err("%s: No read/write API for accessing vdd_%s regs\n",
- __func__, vdd->voltdm.name);
+ if (is_initialized)
return;
- }
-
- mod = vdd->vc_reg.prm_mod;
-
- /* Set up the SMPS_SA(i2c slave address in VC */
- vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_sa_reg);
- vc_val &= ~vdd->vc_reg.smps_sa_mask;
- vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_reg.smps_sa_shift;
- vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_sa_reg);
-
- /* Setup the VOLRA(pmic reg addr) in VC */
- vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_volra_reg);
- vc_val &= ~vdd->vc_reg.smps_volra_mask;
- vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_reg.smps_volra_shift;
- vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_volra_reg);
-
- /*Configure the setup times */
- vc_val = vdd->read_reg(mod, vdd->vc_reg.voltsetup_reg);
- vc_val &= ~vdd->vc_reg.voltsetup_mask;
- vc_val |= vdd->pmic_info->volt_setup_time <<
- vdd->vc_reg.voltsetup_shift;
- vdd->write_reg(vc_val, mod, vdd->vc_reg.voltsetup_reg);
/* Set up the on, inactive, retention and off voltage */
on_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->on_volt);
onlp_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->onlp_volt);
ret_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->ret_volt);
off_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->off_volt);
- vc_val = ((on_vsel << vdd->vc_reg.cmd_on_shift) |
- (onlp_vsel << vdd->vc_reg.cmd_onlp_shift) |
- (ret_vsel << vdd->vc_reg.cmd_ret_shift) |
- (off_vsel << vdd->vc_reg.cmd_off_shift));
- vdd->write_reg(vc_val, mod, vdd->vc_reg.cmdval_reg);
-
- if (is_initialized)
- return;
+ vc_val = ((on_vsel << vdd->vc_data->vc_common->cmd_on_shift) |
+ (onlp_vsel << vdd->vc_data->vc_common->cmd_onlp_shift) |
+ (ret_vsel << vdd->vc_data->vc_common->cmd_ret_shift) |
+ (off_vsel << vdd->vc_data->vc_common->cmd_off_shift));
+ vdd->write_reg(vc_val, prm_mod_offs, vdd->vc_data->cmdval_reg);
- /* Generic VC parameters init */
- vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, mod,
+ /*
+ * Generic VC parameters init
+ * XXX This data should be abstracted out
+ */
+ vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, prm_mod_offs,
OMAP3_PRM_VC_CH_CONF_OFFSET);
- vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, mod,
+ vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, prm_mod_offs,
OMAP3_PRM_VC_I2C_CFG_OFFSET);
- vdd->write_reg(OMAP3_CLKSETUP, mod, OMAP3_PRM_CLKSETUP_OFFSET);
- vdd->write_reg(OMAP3_VOLTOFFSET, mod, OMAP3_PRM_VOLTOFFSET_OFFSET);
- vdd->write_reg(OMAP3_VOLTSETUP2, mod, OMAP3_PRM_VOLTSETUP2_OFFSET);
+
+ omap3_vfsm_init(vdd);
+
is_initialized = true;
}
-/* Sets up all the VDD related info for OMAP3 */
-static int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd)
+
+/* OMAP4 specific voltage init functions */
+static void __init omap4_vc_init(struct omap_vdd_info *vdd)
{
- struct clk *sys_ck;
- u32 sys_clk_speed, timeout_val, waittime;
+ static bool is_initialized;
+ u32 vc_val;
- if (!vdd->pmic_info) {
- pr_err("%s: PMIC info requried to configure vdd_%s not"
- "populated.Hence cannot initialize vdd_%s\n",
- __func__, vdd->voltdm.name, vdd->voltdm.name);
- return -EINVAL;
- }
+ if (is_initialized)
+ return;
- if (!strcmp(vdd->voltdm.name, "mpu")) {
- if (cpu_is_omap3630())
- vdd->volt_data = omap36xx_vddmpu_volt_data;
- else
- vdd->volt_data = omap34xx_vddmpu_volt_data;
-
- vdd->vp_reg.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK;
- vdd->vc_reg.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET;
- vdd->vc_reg.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT;
- vdd->vc_reg.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK;
- vdd->vc_reg.smps_volra_shift = OMAP3430_VOLRA0_SHIFT;
- vdd->vc_reg.smps_volra_mask = OMAP3430_VOLRA0_MASK;
- vdd->vc_reg.voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT;
- vdd->vc_reg.voltsetup_mask = OMAP3430_SETUP_TIME1_MASK;
- } else if (!strcmp(vdd->voltdm.name, "core")) {
- if (cpu_is_omap3630())
- vdd->volt_data = omap36xx_vddcore_volt_data;
- else
- vdd->volt_data = omap34xx_vddcore_volt_data;
-
- vdd->vp_reg.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK;
- vdd->vc_reg.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET;
- vdd->vc_reg.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT;
- vdd->vc_reg.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK;
- vdd->vc_reg.smps_volra_shift = OMAP3430_VOLRA1_SHIFT;
- vdd->vc_reg.smps_volra_mask = OMAP3430_VOLRA1_MASK;
- vdd->vc_reg.voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT;
- vdd->vc_reg.voltsetup_mask = OMAP3430_SETUP_TIME2_MASK;
- } else {
- pr_warning("%s: vdd_%s does not exisit in OMAP3\n",
- __func__, vdd->voltdm.name);
- return -EINVAL;
- }
+ /* TODO: Configure setup times and CMD_VAL values*/
/*
- * Sys clk rate is require to calculate vp timeout value and
- * smpswaittimemin and smpswaittimemax.
+ * Generic VC parameters init
+ * XXX This data should be abstracted out
*/
- sys_ck = clk_get(NULL, "sys_ck");
- if (IS_ERR(sys_ck)) {
- pr_warning("%s: Could not get the sys clk to calculate"
- "various vdd_%s params\n", __func__, vdd->voltdm.name);
- return -EINVAL;
- }
- sys_clk_speed = clk_get_rate(sys_ck);
- clk_put(sys_ck);
- /* Divide to avoid overflow */
- sys_clk_speed /= 1000;
-
- /* Generic voltage parameters */
- vdd->curr_volt = 1200000;
- vdd->ocp_mod = OCP_MOD;
- vdd->prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET;
- vdd->read_reg = omap3_voltage_read_reg;
- vdd->write_reg = omap3_voltage_write_reg;
- vdd->volt_scale = vp_forceupdate_scale_voltage;
- vdd->vp_enabled = false;
+ vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK |
+ OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK |
+ OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK);
+ vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET);
- /* VC parameters */
- vdd->vc_reg.prm_mod = OMAP3430_GR_MOD;
- vdd->vc_reg.smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET;
- vdd->vc_reg.smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET;
- vdd->vc_reg.bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET;
- vdd->vc_reg.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET;
- vdd->vc_reg.data_shift = OMAP3430_DATA_SHIFT;
- vdd->vc_reg.slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT;
- vdd->vc_reg.regaddr_shift = OMAP3430_REGADDR_SHIFT;
- vdd->vc_reg.valid = OMAP3430_VALID_MASK;
- vdd->vc_reg.cmd_on_shift = OMAP3430_VC_CMD_ON_SHIFT;
- vdd->vc_reg.cmd_on_mask = OMAP3430_VC_CMD_ON_MASK;
- vdd->vc_reg.cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT;
- vdd->vc_reg.cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT;
- vdd->vc_reg.cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT;
-
- vdd->vp_reg.prm_mod = OMAP3430_GR_MOD;
-
- /* VPCONFIG bit fields */
- vdd->vp_reg.vpconfig_erroroffset = (vdd->pmic_info->vp_erroroffset <<
- OMAP3430_ERROROFFSET_SHIFT);
- vdd->vp_reg.vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK;
- vdd->vp_reg.vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT;
- vdd->vp_reg.vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT;
- vdd->vp_reg.vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK;
- vdd->vp_reg.vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK;
- vdd->vp_reg.vpconfig_initvdd = OMAP3430_INITVDD_MASK;
- vdd->vp_reg.vpconfig_forceupdate = OMAP3430_FORCEUPDATE_MASK;
- vdd->vp_reg.vpconfig_vpenable = OMAP3430_VPENABLE_MASK;
-
- /* VSTEPMIN VSTEPMAX bit fields */
- waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
- sys_clk_speed) / 1000;
- vdd->vp_reg.vstepmin_smpswaittimemin = waittime;
- vdd->vp_reg.vstepmax_smpswaittimemax = waittime;
- vdd->vp_reg.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
- vdd->vp_reg.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
- vdd->vp_reg.vstepmin_smpswaittimemin_shift =
- OMAP3430_SMPSWAITTIMEMIN_SHIFT;
- vdd->vp_reg.vstepmax_smpswaittimemax_shift =
- OMAP3430_SMPSWAITTIMEMAX_SHIFT;
- vdd->vp_reg.vstepmin_stepmin_shift = OMAP3430_VSTEPMIN_SHIFT;
- vdd->vp_reg.vstepmax_stepmax_shift = OMAP3430_VSTEPMAX_SHIFT;
-
- /* VLIMITTO bit fields */
- timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
- vdd->vp_reg.vlimitto_timeout = timeout_val;
- vdd->vp_reg.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
- vdd->vp_reg.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
- vdd->vp_reg.vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT;
- vdd->vp_reg.vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT;
- vdd->vp_reg.vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT;
+ /* XXX These are magic numbers and do not belong! */
+ vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
+ vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
- return 0;
+ is_initialized = true;
}
-/* OMAP4 specific voltage init functions */
-static void __init omap4_vc_init(struct omap_vdd_info *vdd)
+static void __init omap_vc_init(struct omap_vdd_info *vdd)
{
u32 vc_val;
- u16 mod;
- static bool is_initialized;
if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
pr_err("%s: PMIC info requried to configure vc for"
@@ -948,173 +611,61 @@ static void __init omap4_vc_init(struct omap_vdd_info *vdd)
return;
}
- mod = vdd->vc_reg.prm_mod;
-
/* Set up the SMPS_SA(i2c slave address in VC */
- vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_sa_reg);
- vc_val &= ~vdd->vc_reg.smps_sa_mask;
- vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_reg.smps_sa_shift;
- vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_sa_reg);
+ vc_val = vdd->read_reg(prm_mod_offs,
+ vdd->vc_data->vc_common->smps_sa_reg);
+ vc_val &= ~vdd->vc_data->smps_sa_mask;
+ vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_data->smps_sa_shift;
+ vdd->write_reg(vc_val, prm_mod_offs,
+ vdd->vc_data->vc_common->smps_sa_reg);
/* Setup the VOLRA(pmic reg addr) in VC */
- vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_volra_reg);
- vc_val &= ~vdd->vc_reg.smps_volra_mask;
- vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_reg.smps_volra_shift;
- vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_volra_reg);
-
- /* TODO: Configure setup times and CMD_VAL values*/
-
- if (is_initialized)
- return;
-
- /* Generic VC parameters init */
- vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK |
- OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK |
- OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK);
- vdd->write_reg(vc_val, mod, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET);
-
- vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
- vdd->write_reg(vc_val, mod, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
+ vc_val = vdd->read_reg(prm_mod_offs,
+ vdd->vc_data->vc_common->smps_volra_reg);
+ vc_val &= ~vdd->vc_data->smps_volra_mask;
+ vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_data->smps_volra_shift;
+ vdd->write_reg(vc_val, prm_mod_offs,
+ vdd->vc_data->vc_common->smps_volra_reg);
+
+ /* Configure the setup times */
+ vc_val = vdd->read_reg(prm_mod_offs, vdd->vfsm->voltsetup_reg);
+ vc_val &= ~vdd->vfsm->voltsetup_mask;
+ vc_val |= vdd->pmic_info->volt_setup_time <<
+ vdd->vfsm->voltsetup_shift;
+ vdd->write_reg(vc_val, prm_mod_offs, vdd->vfsm->voltsetup_reg);
- is_initialized = true;
+ if (cpu_is_omap34xx())
+ omap3_vc_init(vdd);
+ else if (cpu_is_omap44xx())
+ omap4_vc_init(vdd);
}
-/* Sets up all the VDD related info for OMAP4 */
-static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
+static int __init omap_vdd_data_configure(struct omap_vdd_info *vdd)
{
- struct clk *sys_ck;
- u32 sys_clk_speed, timeout_val, waittime;
+ int ret = -EINVAL;
if (!vdd->pmic_info) {
pr_err("%s: PMIC info requried to configure vdd_%s not"
"populated.Hence cannot initialize vdd_%s\n",
__func__, vdd->voltdm.name, vdd->voltdm.name);
- return -EINVAL;
+ goto ovdc_out;
}
- if (!strcmp(vdd->voltdm.name, "mpu")) {
- vdd->volt_data = omap44xx_vdd_mpu_volt_data;
- vdd->vp_reg.tranxdone_status =
- OMAP4430_VP_MPU_TRANXDONE_ST_MASK;
- vdd->vc_reg.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET;
- vdd->vc_reg.smps_sa_shift =
- OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT;
- vdd->vc_reg.smps_sa_mask =
- OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK;
- vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT;
- vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK;
- vdd->vc_reg.voltsetup_reg =
- OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET;
- vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET;
- } else if (!strcmp(vdd->voltdm.name, "core")) {
- vdd->volt_data = omap44xx_vdd_core_volt_data;
- vdd->vp_reg.tranxdone_status =
- OMAP4430_VP_CORE_TRANXDONE_ST_MASK;
- vdd->vc_reg.cmdval_reg =
- OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET;
- vdd->vc_reg.smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT;
- vdd->vc_reg.smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK;
- vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT;
- vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK;
- vdd->vc_reg.voltsetup_reg =
- OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET;
- vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET;
- } else if (!strcmp(vdd->voltdm.name, "iva")) {
- vdd->volt_data = omap44xx_vdd_iva_volt_data;
- vdd->vp_reg.tranxdone_status =
- OMAP4430_VP_IVA_TRANXDONE_ST_MASK;
- vdd->vc_reg.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET;
- vdd->vc_reg.smps_sa_shift =
- OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT;
- vdd->vc_reg.smps_sa_mask =
- OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK;
- vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT;
- vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK;
- vdd->vc_reg.voltsetup_reg =
- OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET;
- vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET;
- } else {
- pr_warning("%s: vdd_%s does not exisit in OMAP4\n",
- __func__, vdd->voltdm.name);
- return -EINVAL;
- }
+ if (IS_ERR_VALUE(_config_common_vdd_data(vdd)))
+ goto ovdc_out;
- /*
- * Sys clk rate is require to calculate vp timeout value and
- * smpswaittimemin and smpswaittimemax.
- */
- sys_ck = clk_get(NULL, "sys_clkin_ck");
- if (IS_ERR(sys_ck)) {
- pr_warning("%s: Could not get the sys clk to calculate"
- "various vdd_%s params\n", __func__, vdd->voltdm.name);
- return -EINVAL;
+ if (cpu_is_omap34xx()) {
+ vdd->read_reg = omap3_voltage_read_reg;
+ vdd->write_reg = omap3_voltage_write_reg;
+ ret = 0;
+ } else if (cpu_is_omap44xx()) {
+ vdd->read_reg = omap4_voltage_read_reg;
+ vdd->write_reg = omap4_voltage_write_reg;
+ ret = 0;
}
- sys_clk_speed = clk_get_rate(sys_ck);
- clk_put(sys_ck);
- /* Divide to avoid overflow */
- sys_clk_speed /= 1000;
-
- /* Generic voltage parameters */
- vdd->curr_volt = 1200000;
- vdd->ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST;
- vdd->read_reg = omap4_voltage_read_reg;
- vdd->write_reg = omap4_voltage_write_reg;
- vdd->volt_scale = vp_forceupdate_scale_voltage;
- vdd->vp_enabled = false;
- /* VC parameters */
- vdd->vc_reg.prm_mod = OMAP4430_PRM_DEVICE_INST;
- vdd->vc_reg.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET;
- vdd->vc_reg.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET;
- vdd->vc_reg.bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET;
- vdd->vc_reg.data_shift = OMAP4430_DATA_SHIFT;
- vdd->vc_reg.slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT;
- vdd->vc_reg.regaddr_shift = OMAP4430_REGADDR_SHIFT;
- vdd->vc_reg.valid = OMAP4430_VALID_MASK;
- vdd->vc_reg.cmd_on_shift = OMAP4430_ON_SHIFT;
- vdd->vc_reg.cmd_on_mask = OMAP4430_ON_MASK;
- vdd->vc_reg.cmd_onlp_shift = OMAP4430_ONLP_SHIFT;
- vdd->vc_reg.cmd_ret_shift = OMAP4430_RET_SHIFT;
- vdd->vc_reg.cmd_off_shift = OMAP4430_OFF_SHIFT;
-
- vdd->vp_reg.prm_mod = OMAP4430_PRM_DEVICE_INST;
-
- /* VPCONFIG bit fields */
- vdd->vp_reg.vpconfig_erroroffset = (vdd->pmic_info->vp_erroroffset <<
- OMAP4430_ERROROFFSET_SHIFT);
- vdd->vp_reg.vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK;
- vdd->vp_reg.vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT;
- vdd->vp_reg.vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT;
- vdd->vp_reg.vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK;
- vdd->vp_reg.vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK;
- vdd->vp_reg.vpconfig_initvdd = OMAP4430_INITVDD_MASK;
- vdd->vp_reg.vpconfig_forceupdate = OMAP4430_FORCEUPDATE_MASK;
- vdd->vp_reg.vpconfig_vpenable = OMAP4430_VPENABLE_MASK;
-
- /* VSTEPMIN VSTEPMAX bit fields */
- waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
- sys_clk_speed) / 1000;
- vdd->vp_reg.vstepmin_smpswaittimemin = waittime;
- vdd->vp_reg.vstepmax_smpswaittimemax = waittime;
- vdd->vp_reg.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
- vdd->vp_reg.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
- vdd->vp_reg.vstepmin_smpswaittimemin_shift =
- OMAP4430_SMPSWAITTIMEMIN_SHIFT;
- vdd->vp_reg.vstepmax_smpswaittimemax_shift =
- OMAP4430_SMPSWAITTIMEMAX_SHIFT;
- vdd->vp_reg.vstepmin_stepmin_shift = OMAP4430_VSTEPMIN_SHIFT;
- vdd->vp_reg.vstepmax_stepmax_shift = OMAP4430_VSTEPMAX_SHIFT;
-
- /* VLIMITTO bit fields */
- timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
- vdd->vp_reg.vlimitto_timeout = timeout_val;
- vdd->vp_reg.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
- vdd->vp_reg.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
- vdd->vp_reg.vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT;
- vdd->vp_reg.vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT;
- vdd->vp_reg.vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT;
-
- return 0;
+ovdc_out:
+ return ret;
}
/* Public functions */
@@ -1162,8 +713,7 @@ unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
return 0;
}
- curr_vsel = vdd->read_reg(vdd->vp_reg.prm_mod,
- vdd->vp_offs.voltage);
+ curr_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) {
pr_warning("%s: PMIC function to convert vsel to voltage"
@@ -1185,7 +735,6 @@ void omap_vp_enable(struct voltagedomain *voltdm)
{
struct omap_vdd_info *vdd;
u32 vpconfig;
- u16 mod;
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
@@ -1199,8 +748,6 @@ void omap_vp_enable(struct voltagedomain *voltdm)
return;
}
- mod = vdd->vp_reg.prm_mod;
-
/* If VP is already enabled, do nothing. Return */
if (vdd->vp_enabled)
return;
@@ -1208,9 +755,9 @@ void omap_vp_enable(struct voltagedomain *voltdm)
vp_latch_vsel(vdd);
/* Enable VP */
- vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
- vpconfig |= vdd->vp_reg.vpconfig_vpenable;
- vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+ vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
+ vpconfig |= vdd->vp_data->vp_common->vpconfig_vpenable;
+ vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
vdd->vp_enabled = true;
}
@@ -1225,7 +772,6 @@ void omap_vp_disable(struct voltagedomain *voltdm)
{
struct omap_vdd_info *vdd;
u32 vpconfig;
- u16 mod;
int timeout;
if (!voltdm || IS_ERR(voltdm)) {
@@ -1240,8 +786,6 @@ void omap_vp_disable(struct voltagedomain *voltdm)
return;
}
- mod = vdd->vp_reg.prm_mod;
-
/* If VP is already disabled, do nothing. Return */
if (!vdd->vp_enabled) {
pr_warning("%s: Trying to disable VP for vdd_%s when"
@@ -1250,14 +794,14 @@ void omap_vp_disable(struct voltagedomain *voltdm)
}
/* Disable VP */
- vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
- vpconfig &= ~vdd->vp_reg.vpconfig_vpenable;
- vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+ vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
+ vpconfig &= ~vdd->vp_data->vp_common->vpconfig_vpenable;
+ vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
/*
* Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
*/
- omap_test_timeout((vdd->read_reg(mod, vdd->vp_offs.vstatus)),
+ omap_test_timeout((vdd->read_reg(prm_mod_offs, vdd->vp_data->vstatus)),
VP_IDLE_TIMEOUT, timeout);
if (timeout >= VP_IDLE_TIMEOUT)
@@ -1510,8 +1054,8 @@ struct voltagedomain *omap_voltage_domain_lookup(char *name)
}
for (i = 0; i < nr_scalable_vdd; i++) {
- if (!(strcmp(name, vdd_info[i].voltdm.name)))
- return &vdd_info[i].voltdm;
+ if (!(strcmp(name, vdd_info[i]->voltdm.name)))
+ return &vdd_info[i]->voltdm;
}
return ERR_PTR(-EINVAL);
@@ -1539,35 +1083,24 @@ int __init omap_voltage_late_init(void)
pr_err("%s: Unable to create voltage debugfs main dir\n",
__func__);
for (i = 0; i < nr_scalable_vdd; i++) {
- if (vdd_data_configure(&vdd_info[i]))
+ if (omap_vdd_data_configure(vdd_info[i]))
continue;
- vc_init(&vdd_info[i]);
- vp_init(&vdd_info[i]);
- vdd_debugfs_init(&vdd_info[i]);
+ omap_vc_init(vdd_info[i]);
+ vp_init(vdd_info[i]);
+ vdd_debugfs_init(vdd_info[i]);
}
return 0;
}
-/**
- * omap_voltage_early_init()- Volatage driver early init
- */
-static int __init omap_voltage_early_init(void)
+/* XXX document */
+int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_ocp_mod,
+ struct omap_vdd_info *omap_vdd_array[],
+ u8 omap_vdd_count)
{
- if (cpu_is_omap34xx()) {
- vdd_info = omap3_vdd_info;
- nr_scalable_vdd = OMAP3_NR_SCALABLE_VDD;
- vc_init = omap3_vc_init;
- vdd_data_configure = omap3_vdd_data_configure;
- } else if (cpu_is_omap44xx()) {
- vdd_info = omap4_vdd_info;
- nr_scalable_vdd = OMAP4_NR_SCALABLE_VDD;
- vc_init = omap4_vc_init;
- vdd_data_configure = omap4_vdd_data_configure;
- } else {
- pr_warning("%s: voltage driver support not added\n", __func__);
- }
-
+ prm_mod_offs = prm_mod;
+ prm_irqst_ocp_mod_offs = prm_irqst_ocp_mod;
+ vdd_info = omap_vdd_array;
+ nr_scalable_vdd = omap_vdd_count;
return 0;
}
-core_initcall(omap_voltage_early_init);
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index 5bd204e..e9f5408 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -16,6 +16,10 @@
#include <linux/err.h>
+#include "vc.h"
+#include "vp.h"
+
+/* XXX document */
#define VOLTSCALE_VPFORCEUPDATE 1
#define VOLTSCALE_VCBYPASS 2
@@ -27,36 +31,22 @@
#define OMAP3_VOLTOFFSET 0xff
#define OMAP3_VOLTSETUP2 0xff
-/* Voltage value defines */
-#define OMAP3430_VDD_MPU_OPP1_UV 975000
-#define OMAP3430_VDD_MPU_OPP2_UV 1075000
-#define OMAP3430_VDD_MPU_OPP3_UV 1200000
-#define OMAP3430_VDD_MPU_OPP4_UV 1270000
-#define OMAP3430_VDD_MPU_OPP5_UV 1350000
-
-#define OMAP3430_VDD_CORE_OPP1_UV 975000
-#define OMAP3430_VDD_CORE_OPP2_UV 1050000
-#define OMAP3430_VDD_CORE_OPP3_UV 1150000
-
-#define OMAP3630_VDD_MPU_OPP50_UV 1012500
-#define OMAP3630_VDD_MPU_OPP100_UV 1200000
-#define OMAP3630_VDD_MPU_OPP120_UV 1325000
-#define OMAP3630_VDD_MPU_OPP1G_UV 1375000
-
-#define OMAP3630_VDD_CORE_OPP50_UV 1000000
-#define OMAP3630_VDD_CORE_OPP100_UV 1200000
-
-#define OMAP4430_VDD_MPU_OPP50_UV 930000
-#define OMAP4430_VDD_MPU_OPP100_UV 1100000
-#define OMAP4430_VDD_MPU_OPPTURBO_UV 1260000
-#define OMAP4430_VDD_MPU_OPPNITRO_UV 1350000
-
-#define OMAP4430_VDD_IVA_OPP50_UV 930000
-#define OMAP4430_VDD_IVA_OPP100_UV 1100000
-#define OMAP4430_VDD_IVA_OPPTURBO_UV 1260000
-
-#define OMAP4430_VDD_CORE_OPP50_UV 930000
-#define OMAP4430_VDD_CORE_OPP100_UV 1100000
+/**
+ * struct omap_vfsm_instance_data - per-voltage manager FSM register/bitfield
+ * data
+ * @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register
+ * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base
+ * @voltsetup_shift: SETUP_TIME* field shift in the PRM_VOLTSETUP* register
+ *
+ * XXX What about VOLTOFFSET/VOLTCTRL?
+ * XXX It is not necessary to have both a _mask and a _shift for the same
+ * bitfield - remove one!
+ */
+struct omap_vfsm_instance_data {
+ u32 voltsetup_mask;
+ u8 voltsetup_reg;
+ u8 voltsetup_shift;
+};
/**
* struct voltagedomain - omap voltage domain global structure.
@@ -113,6 +103,42 @@ struct omap_volt_pmic_info {
u8 (*uv_to_vsel) (unsigned long uV);
};
+/**
+ * omap_vdd_info - Per Voltage Domain info
+ *
+ * @volt_data : voltage table having the distinct voltages supported
+ * by the domain and other associated per voltage data.
+ * @pmic_info : pmic specific parameters which should be populted by
+ * the pmic drivers.
+ * @vp_data : the register values, shifts, masks for various
+ * vp registers
+ * @vp_rt_data : VP data derived at runtime, not predefined
+ * @vc_data : structure containing various various vc registers,
+ * shifts, masks etc.
+ * @vfsm : voltage manager FSM data
+ * @voltdm : pointer to the voltage domain structure
+ * @debug_dir : debug directory for this voltage domain.
+ * @curr_volt : current voltage for this vdd.
+ * @vp_enabled : flag to keep track of whether vp is enabled or not
+ * @volt_scale : API to scale the voltage of the vdd.
+ */
+struct omap_vdd_info {
+ struct omap_volt_data *volt_data;
+ struct omap_volt_pmic_info *pmic_info;
+ struct omap_vp_instance_data *vp_data;
+ struct omap_vp_runtime_data vp_rt_data;
+ struct omap_vc_instance_data *vc_data;
+ const struct omap_vfsm_instance_data *vfsm;
+ struct voltagedomain voltdm;
+ struct dentry *debug_dir;
+ u32 curr_volt;
+ bool vp_enabled;
+ u32 (*read_reg) (u16 mod, u8 offset);
+ void (*write_reg) (u32 val, u16 mod, u8 offset);
+ int (*volt_scale) (struct omap_vdd_info *vdd,
+ unsigned long target_volt);
+};
+
unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm);
void omap_vp_enable(struct voltagedomain *voltdm);
void omap_vp_disable(struct voltagedomain *voltdm);
@@ -125,6 +151,9 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
unsigned long volt);
unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm);
struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);
+int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod,
+ struct omap_vdd_info *omap_vdd_array[],
+ u8 omap_vdd_count);
#ifdef CONFIG_PM
int omap_voltage_register_pmic(struct voltagedomain *voltdm,
struct omap_volt_pmic_info *pmic_info);
diff --git a/arch/arm/mach-omap2/voltagedomains3xxx_data.c b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
new file mode 100644
index 0000000..def230f
--- /dev/null
+++ b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
@@ -0,0 +1,95 @@
+/*
+ * OMAP3 voltage domain data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+#include <plat/cpu.h>
+
+#include "prm-regbits-34xx.h"
+#include "omap_opp_data.h"
+#include "voltage.h"
+#include "vc.h"
+#include "vp.h"
+
+/*
+ * VDD data
+ */
+
+static const struct omap_vfsm_instance_data omap3_vdd1_vfsm_data = {
+ .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
+ .voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT,
+ .voltsetup_mask = OMAP3430_SETUP_TIME1_MASK,
+};
+
+static struct omap_vdd_info omap3_vdd1_info = {
+ .vp_data = &omap3_vp1_data,
+ .vc_data = &omap3_vc1_data,
+ .vfsm = &omap3_vdd1_vfsm_data,
+ .voltdm = {
+ .name = "mpu",
+ },
+};
+
+static const struct omap_vfsm_instance_data omap3_vdd2_vfsm_data = {
+ .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
+ .voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT,
+ .voltsetup_mask = OMAP3430_SETUP_TIME2_MASK,
+};
+
+static struct omap_vdd_info omap3_vdd2_info = {
+ .vp_data = &omap3_vp2_data,
+ .vc_data = &omap3_vc2_data,
+ .vfsm = &omap3_vdd2_vfsm_data,
+ .voltdm = {
+ .name = "core",
+ },
+};
+
+/* OMAP3 VDD structures */
+static struct omap_vdd_info *omap3_vdd_info[] = {
+ &omap3_vdd1_info,
+ &omap3_vdd2_info,
+};
+
+/* OMAP3 specific voltage init functions */
+static int __init omap3xxx_voltage_early_init(void)
+{
+ s16 prm_mod = OMAP3430_GR_MOD;
+ s16 prm_irqst_ocp_mod = OCP_MOD;
+
+ if (!cpu_is_omap34xx())
+ return 0;
+
+ /*
+ * XXX Will depend on the process, validation, and binning
+ * for the currently-running IC
+ */
+ if (cpu_is_omap3630()) {
+ omap3_vdd1_info.volt_data = omap36xx_vddmpu_volt_data;
+ omap3_vdd2_info.volt_data = omap36xx_vddcore_volt_data;
+ } else {
+ omap3_vdd1_info.volt_data = omap34xx_vddmpu_volt_data;
+ omap3_vdd2_info.volt_data = omap34xx_vddcore_volt_data;
+ }
+
+ return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
+ omap3_vdd_info,
+ ARRAY_SIZE(omap3_vdd_info));
+};
+core_initcall(omap3xxx_voltage_early_init);
diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c b/arch/arm/mach-omap2/voltagedomains44xx_data.c
new file mode 100644
index 0000000..cb64996
--- /dev/null
+++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c
@@ -0,0 +1,102 @@
+/*
+ * OMAP3/OMAP4 Voltage Management Routines
+ *
+ * Author: Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+#include "prcm44xx.h"
+#include "prminst44xx.h"
+#include "voltage.h"
+#include "omap_opp_data.h"
+#include "vc.h"
+#include "vp.h"
+
+static const struct omap_vfsm_instance_data omap4_vdd_mpu_vfsm_data = {
+ .voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET,
+};
+
+static struct omap_vdd_info omap4_vdd_mpu_info = {
+ .vp_data = &omap4_vp_mpu_data,
+ .vc_data = &omap4_vc_mpu_data,
+ .vfsm = &omap4_vdd_mpu_vfsm_data,
+ .voltdm = {
+ .name = "mpu",
+ },
+};
+
+static const struct omap_vfsm_instance_data omap4_vdd_iva_vfsm_data = {
+ .voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
+};
+
+static struct omap_vdd_info omap4_vdd_iva_info = {
+ .vp_data = &omap4_vp_iva_data,
+ .vc_data = &omap4_vc_iva_data,
+ .vfsm = &omap4_vdd_iva_vfsm_data,
+ .voltdm = {
+ .name = "iva",
+ },
+};
+
+static const struct omap_vfsm_instance_data omap4_vdd_core_vfsm_data = {
+ .voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
+};
+
+static struct omap_vdd_info omap4_vdd_core_info = {
+ .vp_data = &omap4_vp_core_data,
+ .vc_data = &omap4_vc_core_data,
+ .vfsm = &omap4_vdd_core_vfsm_data,
+ .voltdm = {
+ .name = "core",
+ },
+};
+
+/* OMAP4 VDD structures */
+static struct omap_vdd_info *omap4_vdd_info[] = {
+ &omap4_vdd_mpu_info,
+ &omap4_vdd_iva_info,
+ &omap4_vdd_core_info,
+};
+
+/* OMAP4 specific voltage init functions */
+static int __init omap44xx_voltage_early_init(void)
+{
+ s16 prm_mod = OMAP4430_PRM_DEVICE_INST;
+ s16 prm_irqst_ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST;
+
+ if (!cpu_is_omap44xx())
+ return 0;
+
+ /*
+ * XXX Will depend on the process, validation, and binning
+ * for the currently-running IC
+ */
+ omap4_vdd_mpu_info.volt_data = omap44xx_vdd_mpu_volt_data;
+ omap4_vdd_iva_info.volt_data = omap44xx_vdd_iva_volt_data;
+ omap4_vdd_core_info.volt_data = omap44xx_vdd_core_volt_data;
+
+ return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
+ omap4_vdd_info,
+ ARRAY_SIZE(omap4_vdd_info));
+};
+core_initcall(omap44xx_voltage_early_init);
diff --git a/arch/arm/mach-omap2/vp.h b/arch/arm/mach-omap2/vp.h
new file mode 100644
index 0000000..7ce134f
--- /dev/null
+++ b/arch/arm/mach-omap2/vp.h
@@ -0,0 +1,143 @@
+/*
+ * OMAP3/4 Voltage Processor (VP) structure and macro definitions
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+#ifndef __ARCH_ARM_MACH_OMAP2_VP_H
+#define __ARCH_ARM_MACH_OMAP2_VP_H
+
+#include <linux/kernel.h>
+
+/* XXX document */
+#define VP_IDLE_TIMEOUT 200
+#define VP_TRANXDONE_TIMEOUT 300
+
+
+/**
+ * struct omap_vp_common_data - register data common to all VDDs
+ * @vpconfig_errorgain_mask: ERRORGAIN bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_initvoltage_mask: INITVOLTAGE bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_timeouten_mask: TIMEOUT bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_initvdd: INITVDD bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_forceupdate: FORCEUPDATE bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_vpenable: VPENABLE bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_erroroffset_shift: ERROROFFSET field shift in PRM_VP*_CONFIG reg
+ * @vpconfig_errorgain_shift: ERRORGAIN field shift in PRM_VP*_CONFIG reg
+ * @vpconfig_initvoltage_shift: INITVOLTAGE field shift in PRM_VP*_CONFIG reg
+ * @vpconfig_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
+ * @vpconfig_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
+ * @vpconfig_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
+ * @vpconfig_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
+ * @vpconfig_vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
+ * @vpconfig_vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
+ * @vpconfig_vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
+ *
+ * XXX It it not necessary to have both a mask and a shift for the same
+ * bitfield - remove one
+ * XXX Many of these fields are wrongly named -- e.g., vpconfig_smps* -- fix!
+ */
+struct omap_vp_common_data {
+ u32 vpconfig_errorgain_mask;
+ u32 vpconfig_initvoltage_mask;
+ u32 vpconfig_timeouten;
+ u32 vpconfig_initvdd;
+ u32 vpconfig_forceupdate;
+ u32 vpconfig_vpenable;
+ u8 vpconfig_erroroffset_shift;
+ u8 vpconfig_errorgain_shift;
+ u8 vpconfig_initvoltage_shift;
+ u8 vstepmin_stepmin_shift;
+ u8 vstepmin_smpswaittimemin_shift;
+ u8 vstepmax_stepmax_shift;
+ u8 vstepmax_smpswaittimemax_shift;
+ u8 vlimitto_vddmin_shift;
+ u8 vlimitto_vddmax_shift;
+ u8 vlimitto_timeout_shift;
+};
+
+/**
+ * struct omap_vp_prm_irqst_data - PRM_IRQSTATUS_MPU.VP_TRANXDONE_ST data
+ * @prm_irqst_reg: reg offset for PRM_IRQSTATUS_MPU from top of PRM
+ * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ *
+ * XXX prm_irqst_reg does not belong here
+ * XXX Note that on OMAP3, VP_TRANXDONE interrupt may not work due to a
+ * hardware bug
+ * XXX This structure is probably not needed
+ */
+struct omap_vp_prm_irqst_data {
+ u8 prm_irqst_reg;
+ u32 tranxdone_status;
+};
+
+/**
+ * struct omap_vp_instance_data - VP register offsets (per-VDD)
+ * @vp_common: pointer to struct omap_vp_common_data * for this SoC
+ * @prm_irqst_data: pointer to struct omap_vp_prm_irqst_data for this VDD
+ * @vpconfig: PRM_VP*_CONFIG reg offset from PRM start
+ * @vstepmin: PRM_VP*_VSTEPMIN reg offset from PRM start
+ * @vlimitto: PRM_VP*_VLIMITTO reg offset from PRM start
+ * @vstatus: PRM_VP*_VSTATUS reg offset from PRM start
+ * @voltage: PRM_VP*_VOLTAGE reg offset from PRM start
+ *
+ * XXX vp_common is probably not needed since it is per-SoC
+ */
+struct omap_vp_instance_data {
+ const struct omap_vp_common_data *vp_common;
+ const struct omap_vp_prm_irqst_data *prm_irqst_data;
+ u8 vpconfig;
+ u8 vstepmin;
+ u8 vstepmax;
+ u8 vlimitto;
+ u8 vstatus;
+ u8 voltage;
+};
+
+/**
+ * struct omap_vp_runtime_data - VP data populated at runtime by code
+ * @vpconfig_erroroffset: value of ERROROFFSET bitfield in PRM_VP*_CONFIG
+ * @vpconfig_errorgain: value of ERRORGAIN bitfield in PRM_VP*_CONFIG
+ * @vstepmin_smpswaittimemin: value of SMPSWAITTIMEMIN bitfield in PRM_VP*_VSTEPMIN
+ * @vstepmax_smpswaittimemax: value of SMPSWAITTIMEMAX bitfield in PRM_VP*_VSTEPMAX
+ * @vlimitto_timeout: value of TIMEOUT bitfield in PRM_VP*_VLIMITTO
+ * @vstepmin_stepmin: value of VSTEPMIN bitfield in PRM_VP*_VSTEPMIN
+ * @vstepmax_stepmax: value of VSTEPMAX bitfield in PRM_VP*_VSTEPMAX
+ * @vlimitto_vddmin: value of VDDMIN bitfield in PRM_VP*_VLIMITTO
+ * @vlimitto_vddmax: value of VDDMAX bitfield in PRM_VP*_VLIMITTO
+ *
+ * XXX Is this structure really needed? Why not just program the
+ * device directly? They are in PRM space, therefore in the WKUP
+ * powerdomain, so register contents should not be lost in off-mode.
+ * XXX Some of these fields are incorrectly named, e.g., vstep*
+ */
+struct omap_vp_runtime_data {
+ u32 vpconfig_erroroffset;
+ u16 vpconfig_errorgain;
+ u16 vstepmin_smpswaittimemin;
+ u16 vstepmax_smpswaittimemax;
+ u16 vlimitto_timeout;
+ u8 vstepmin_stepmin;
+ u8 vstepmax_stepmax;
+ u8 vlimitto_vddmin;
+ u8 vlimitto_vddmax;
+};
+
+extern struct omap_vp_instance_data omap3_vp1_data;
+extern struct omap_vp_instance_data omap3_vp2_data;
+
+extern struct omap_vp_instance_data omap4_vp_mpu_data;
+extern struct omap_vp_instance_data omap4_vp_iva_data;
+extern struct omap_vp_instance_data omap4_vp_core_data;
+
+#endif
diff --git a/arch/arm/mach-omap2/vp3xxx_data.c b/arch/arm/mach-omap2/vp3xxx_data.c
new file mode 100644
index 0000000..6452170
--- /dev/null
+++ b/arch/arm/mach-omap2/vp3xxx_data.c
@@ -0,0 +1,82 @@
+/*
+ * OMAP3 Voltage Processor (VP) data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm-regbits-34xx.h"
+#include "voltage.h"
+
+#include "vp.h"
+
+/*
+ * VP data common to 34xx/36xx chips
+ * XXX This stuff presumably belongs in the vp3xxx.c or vp.c file.
+ */
+static const struct omap_vp_common_data omap3_vp_common = {
+ .vpconfig_erroroffset_shift = OMAP3430_ERROROFFSET_SHIFT,
+ .vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK,
+ .vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT,
+ .vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT,
+ .vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK,
+ .vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK,
+ .vpconfig_initvdd = OMAP3430_INITVDD_MASK,
+ .vpconfig_forceupdate = OMAP3430_FORCEUPDATE_MASK,
+ .vpconfig_vpenable = OMAP3430_VPENABLE_MASK,
+ .vstepmin_smpswaittimemin_shift = OMAP3430_SMPSWAITTIMEMIN_SHIFT,
+ .vstepmax_smpswaittimemax_shift = OMAP3430_SMPSWAITTIMEMAX_SHIFT,
+ .vstepmin_stepmin_shift = OMAP3430_VSTEPMIN_SHIFT,
+ .vstepmax_stepmax_shift = OMAP3430_VSTEPMAX_SHIFT,
+ .vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT,
+ .vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT,
+ .vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT,
+};
+
+static const struct omap_vp_prm_irqst_data omap3_vp1_prm_irqst_data = {
+ .prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
+ .tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap3_vp1_data = {
+ .vp_common = &omap3_vp_common,
+ .vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET,
+ .vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
+ .vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
+ .vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET,
+ .vstatus = OMAP3_PRM_VP1_STATUS_OFFSET,
+ .voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET,
+ .prm_irqst_data = &omap3_vp1_prm_irqst_data,
+};
+
+static const struct omap_vp_prm_irqst_data omap3_vp2_prm_irqst_data = {
+ .prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
+ .tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap3_vp2_data = {
+ .vp_common = &omap3_vp_common,
+ .vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET,
+ .vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
+ .vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
+ .vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET,
+ .vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
+ .voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
+ .prm_irqst_data = &omap3_vp2_prm_irqst_data,
+};
diff --git a/arch/arm/mach-omap2/vp44xx_data.c b/arch/arm/mach-omap2/vp44xx_data.c
new file mode 100644
index 0000000..7b26f75
--- /dev/null
+++ b/arch/arm/mach-omap2/vp44xx_data.c
@@ -0,0 +1,97 @@
+/*
+ * OMAP3 Voltage Processor (VP) data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm44xx.h"
+#include "prm-regbits-44xx.h"
+#include "voltage.h"
+
+#include "vp.h"
+
+/*
+ * VP data common to 44xx chips
+ * XXX This stuff presumably belongs in the vp44xx.c or vp.c file.
+ */
+static const struct omap_vp_common_data omap4_vp_data = {
+ .vpconfig_erroroffset_shift = OMAP4430_ERROROFFSET_SHIFT,
+ .vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK,
+ .vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT,
+ .vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT,
+ .vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK,
+ .vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK,
+ .vpconfig_initvdd = OMAP4430_INITVDD_MASK,
+ .vpconfig_forceupdate = OMAP4430_FORCEUPDATE_MASK,
+ .vpconfig_vpenable = OMAP4430_VPENABLE_MASK,
+ .vstepmin_smpswaittimemin_shift = OMAP4430_SMPSWAITTIMEMIN_SHIFT,
+ .vstepmax_smpswaittimemax_shift = OMAP4430_SMPSWAITTIMEMAX_SHIFT,
+ .vstepmin_stepmin_shift = OMAP4430_VSTEPMIN_SHIFT,
+ .vstepmax_stepmax_shift = OMAP4430_VSTEPMAX_SHIFT,
+ .vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT,
+ .vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT,
+ .vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT,
+};
+
+static const struct omap_vp_prm_irqst_data omap4_vp_mpu_prm_irqst_data = {
+ .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
+ .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap4_vp_mpu_data = {
+ .vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET,
+ .vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET,
+ .vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET,
+ .vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET,
+ .vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET,
+ .voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET,
+ .prm_irqst_data = &omap4_vp_mpu_prm_irqst_data,
+};
+
+static const struct omap_vp_prm_irqst_data omap4_vp_iva_prm_irqst_data = {
+ .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+ .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap4_vp_iva_data = {
+ .vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET,
+ .vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET,
+ .vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET,
+ .vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET,
+ .vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET,
+ .voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET,
+ .prm_irqst_data = &omap4_vp_iva_prm_irqst_data,
+};
+
+static const struct omap_vp_prm_irqst_data omap4_vp_core_prm_irqst_data = {
+ .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+ .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap4_vp_core_data = {
+ .vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET,
+ .vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET,
+ .vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET,
+ .vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET,
+ .vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
+ .voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
+ .prm_irqst_data = &omap4_vp_core_prm_irqst_data,
+};
+
--
1.7.2.3
^ permalink raw reply related
* [PATCH 2/5] ARM: omap: update GPIO chained IRQ handler to use EOI in parent chip
From: Santosh Shilimkar @ 2011-02-21 19:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298302096-21275-3-git-send-email-will.deacon@arm.com>
> -----Original Message-----
> From: Will Deacon [mailto:will.deacon at arm.com]
> Sent: Monday, February 21, 2011 8:58 PM
> To: linux-arm-kernel at lists.infradead.org
> Cc: linux at arm.linux.org.uk; adharmap at codeaurora.org; rabin at rab.in;
> tglx at linutronix.de; catalin.marinas at arm.com;
> santosh.shilimkar at ti.com; ccross at google.com;
> kyungmin.park at samsung.com; Will Deacon
> Subject: [PATCH 2/5] ARM: omap: update GPIO chained IRQ handler to
> use EOI in parent chip
>
> On OMAP4, gpio_irq_handler can be chained to a physical interrupt
> using
> the GIC as the primary IRQ chip. Now that the GIC uses the fasteoi
> flow
> model, the chained handler must invoke ->irq_eoi once handling is
> complete.
>
> This patch adds a conditional call to ->irq_eoi in the GPIO IRQ
> handler
> for OMAP platforms. For OMAP implementations using other primary
> interrupt controllers, the ->irq_ack call remains and is also made
> conditional on the support offered by the controller.
>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Colin Cross <ccross@google.com>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> ---
Thanks Will for changes. They look fine.
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
I will test your series tomorrow on OMAP with some
GPIO interrupts.
> arch/arm/plat-omap/gpio.c | 5 ++++-
> 1 files changed, 4 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
> index 971d186..1d2d1c7 100644
> --- a/arch/arm/plat-omap/gpio.c
> +++ b/arch/arm/plat-omap/gpio.c
> @@ -1144,7 +1144,8 @@ static void gpio_irq_handler(unsigned int irq,
> struct irq_desc *desc)
> u32 retrigger = 0;
> int unmasked = 0;
>
> - desc->irq_data.chip->irq_ack(&desc->irq_data);
> + if (desc->irq_data.chip->irq_ack)
> + desc->irq_data.chip->irq_ack(&desc->irq_data);
>
> bank = get_irq_data(irq);
> #ifdef CONFIG_ARCH_OMAP1
> @@ -1238,6 +1239,8 @@ static void gpio_irq_handler(unsigned int irq,
> struct irq_desc *desc)
> exit:
> if (!unmasked)
> desc->irq_data.chip->irq_unmask(&desc->irq_data);
> + if (desc->irq_data.chip->irq_eoi)
> + desc->irq_data.chip->irq_eoi(&desc->irq_data);
> }
>
> static void gpio_irq_shutdown(struct irq_data *d)
> --
> 1.7.0.4
>
^ permalink raw reply
* [PATCH 1/2] PRUSS UIO driver support
From: Hans J. Koch @ 2011-02-21 19:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <B85A65D85D7EB246BE421B3FB0FBB593024B83C20F@dbde02.ent.ti.com>
On Mon, Feb 21, 2011 at 09:27:47AM +0530, TK, Pratheesh Gangadhar wrote:
> Hi Hans,
>
> > -----Original Message-----
> > From: Hans J. Koch [mailto:hjk at hansjkoch.de]
> > Sent: Sunday, February 20, 2011 12:04 AM
> > To: TK, Pratheesh Gangadhar
> > Cc: Thomas Gleixner; Arnd Bergmann; linux-arm-kernel at lists.infradead.org;
> > davinci-linux-open-source at linux.davincidsp.com; gregkh at suse.de;
> > Chatterjee, Amit; Hans J. Koch; LKML
> > Subject: Re: [PATCH 1/2] PRUSS UIO driver support
> >
> > On Sat, Feb 19, 2011 at 09:10:23PM +0530, TK, Pratheesh Gangadhar wrote:
> > >
> > > For my understanding - if the interrupt is not shared and not level
> > triggered -
> > > is this okay to have empty handler?
> >
> > Greg already said he won't accept that. And I'm quite sure these
> > interrupts
> > are level triggered, since that is the default on arch/omap.
> >
> > E.g. in arch/arm/mach-omap1/irq.c, a loop sets all irqs to level triggered
> > handling: set_irq_handler(j, handle_level_irq); (line 234)
>
> You should be looking at arch/arm/mach-davinci/irq.c
Hmpf. I alway get lost in the directory structure of TI SoCs...
At least I learned that OMAP3 is in the omap2 directory :)
> and all interrupts except IRQ_TINT1_TINT34 is set to edge trigger mode (line 160).
Is that really needed? Level triggered interrupts should certainly be
preferred if possible.
Thanks,
Hans
^ permalink raw reply
* [PATCH 1/2] PRUSS UIO driver support
From: Thomas Gleixner @ 2011-02-21 19:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110221193316.GC2773@local>
On Mon, 21 Feb 2011, Hans J. Koch wrote:
> On Mon, Feb 21, 2011 at 09:27:47AM +0530, TK, Pratheesh Gangadhar wrote:
> > and all interrupts except IRQ_TINT1_TINT34 is set to edge trigger mode (line 160).
>
> Is that really needed? Level triggered interrupts should certainly be
> preferred if possible.
Nonsense. If you have a sane interrupt controller which latches the
edge transitions even when masked, edge type interrupts are perfectly
fine.
Thanks,
tglx
^ permalink raw reply
* [PATCH 2/2] clk: Generic support for fixed-rate clocks
From: Ryan Mallon @ 2011-02-21 19:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298256658.862488.956979497586.2.gpush@pororo>
On 02/21/2011 03:50 PM, Jeremy Kerr wrote:
> Since most platforms will need a fixed-rate clock, add one. This will
> also serve as a basic example of an implementation of struct clk.
>
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>
> ---
> drivers/clk/clk.c | 14 ++++++++++++++
> include/linux/clk.h | 16 ++++++++++++++++
> 2 files changed, 30 insertions(+)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 0bc9c6f..0da0bb9 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -130,3 +130,17 @@ void __clk_put(struct clk *clk)
> if (clk->ops->put)
> clk->ops->put(clk);
> }
> +
> +/* clk_fixed support */
> +
> +#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
> +
> +static unsigned long clk_fixed_get_rate(struct clk *clk)
> +{
> + return to_clk_fixed(clk)->rate;
> +}
> +
> +struct clk_ops clk_fixed_ops = {
> + .get_rate = clk_fixed_get_rate,
> +};
> +EXPORT_SYMBOL_GPL(clk_fixed_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 604be74..7c0808c 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -155,6 +155,22 @@ static inline void clk_common_init(struct clk *clk)
> mutex_init(&clk->prepare_lock);
> }
>
> +/* Simple fixed-rate clock */
> +struct clk_fixed {
> + struct clk clk;
> + unsigned long rate;
If we never need to dynamically create fixed clocks (which seems
unlikely) then rate can be const.
~Ryan
--
Bluewater Systems Ltd - ARM Technology Solution Centre
Ryan Mallon 5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com New Zealand
Phone: +64 3 3779127 Freecall: Australia 1800 148 751
Fax: +64 3 3779135 USA 1800 261 2934
^ permalink raw reply
* [PATCH 1/2] PRUSS UIO driver support
From: Sergei Shtylyov @ 2011-02-21 19:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110221193316.GC2773@local>
Hello.
Hans J. Koch wrote:
>>> -----Original Message-----
>>> From: Hans J. Koch [mailto:hjk at hansjkoch.de]
>>> Sent: Sunday, February 20, 2011 12:04 AM
>>> To: TK, Pratheesh Gangadhar
>>> Cc: Thomas Gleixner; Arnd Bergmann; linux-arm-kernel at lists.infradead.org;
>>> davinci-linux-open-source at linux.davincidsp.com; gregkh at suse.de;
>>> Chatterjee, Amit; Hans J. Koch; LKML
>>> Subject: Re: [PATCH 1/2] PRUSS UIO driver support
>>> On Sat, Feb 19, 2011 at 09:10:23PM +0530, TK, Pratheesh Gangadhar wrote:
>>>> For my understanding - if the interrupt is not shared and not level triggered -
>>>> is this okay to have empty handler?
>>> Greg already said he won't accept that. And I'm quite sure these
>>> interrupts
>>> are level triggered, since that is the default on arch/omap.
>>> E.g. in arch/arm/mach-omap1/irq.c, a loop sets all irqs to level triggered
>>> handling: set_irq_handler(j, handle_level_irq); (line 234)
>> You should be looking at arch/arm/mach-davinci/irq.c
Into arch/arm/mach-davinci/cp_intc.c actually as we're not talking about a
"real" DaVincis here, but about OMAP-L138.
> Hmpf. I alway get lost in the directory structure of TI SoCs...
> At least I learned that OMAP3 is in the omap2 directory :)
It's probably even more convoluted with DaVinci and friends. :-)
>> and all interrupts except IRQ_TINT1_TINT34 is set to edge trigger mode (line 160).
> Is that really needed? Level triggered interrupts should certainly be
> preferred if possible.
Don't look there, this code is for "real" DaVincis only.
> Thanks,
> Hans
WBR, Sergei
^ permalink raw reply
* dma_declare_coherent_memory() again.
From: Philippe Rétornaz @ 2011-02-21 20:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <Pine.LNX.4.64.1102211602140.26977@axis700.grange>
Le lundi, 21 f?vrier 2011 16.37:00, Guennadi Liakhovetski a ?crit :
> Hi All
>
> AFAIU, dma_declare_coherent_memory() is still present on the following
> platforms:
>
(...)
> arch/arm/mach-mx3/mach-mx31moboard.c
(...)
> and there are no pending patches to fix them for 2.6.38, is this right? If
> there are no realistic plans for proper memory reservation on ARM in
> 2.6.38, shall I just submit patches to disable those calls on the above
> platforms and hope, that the user manages to get RAM without boot-time
> reservation? Or is a definite failure preferred?
I won't have the time to patch this before 2.6.38, but I plan to rebase my
tree in the next couple of months. So you can either break it or just remove
the call but AFAIK in both case it won't work as you cannot allocate a such
big buffer without special pool.
Thanks,
Philippe
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox