* [PATCH 2/3] dmaengine: dw_dmac: Enhance device tree support
From: Viresh Kumar @ 2012-10-12 5:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <142ef9170a2c69657d8a05ac127a9970d7b04965.1350020375.git.viresh.kumar@linaro.org>
dw_dmac driver already supports device tree but it used to have its platform
data passed the non-DT way.
This patch does following changes:
- pass platform data via DT, non-DT way still takes precedence if both are used.
- create generic filter routine
- Earlier slave information was made available by slave specific filter routines
in chan->private field. Now, this information would be passed from within dmac
DT node. Slave drivers would now be required to pass bus_id (a string) as
parameter to this generic filter(), which would be compared against the slave
data passed from DT, by the generic filter routine.
- Update binding document
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
Documentation/devicetree/bindings/dma/snps-dma.txt | 44 ++++++
drivers/dma/dw_dmac.c | 147 +++++++++++++++++++++
drivers/dma/dw_dmac_regs.h | 4 +
include/linux/dw_dmac.h | 43 +++---
4 files changed, 221 insertions(+), 17 deletions(-)
diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index c0d85db..5bb3dfb 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -6,6 +6,26 @@ Required properties:
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device
- interrupt: Should contain the DMAC interrupt number
+- nr_channels: Number of channels supported by hardware
+- is_private: The device channels should be marked as private and not for by the
+ general purpose DMA channel allocator. False if not passed.
+- chan_allocation_order: order of allocation of channel, 0 (default): ascending,
+ 1: descending
+- chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
+ increase from chan n->0
+- block_size: Maximum block size supported by the controller
+- nr_masters: Number of AHB masters supported by the controller
+- data_width: Maximum data width supported by hardware per AHB master
+ (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
+- slave_info:
+ - bus_id: name of this device channel, not just a device name since
+ devices may have more than one channel e.g. "foo_tx". For using the
+ dw_generic_filter(), slave drivers must pass exactly this string as
+ param to filter function.
+ - cfg_hi: Platform-specific initializer for the CFG_HI register
+ - cfg_lo: Platform-specific initializer for the CFG_LO register
+ - src_master: src master for transfers on allocated channel.
+ - dst_master: dest master for transfers on allocated channel.
Example:
@@ -14,4 +34,28 @@ Example:
reg = <0xfc000000 0x1000>;
interrupt-parent = <&vic1>;
interrupts = <12>;
+
+ nr_channels = <8>;
+ chan_allocation_order = <1>;
+ chan_priority = <1>;
+ block_size = <0xfff>;
+ nr_masters = <2>;
+ data_width = <3 3 0 0>;
+
+ slave_info {
+ uart0-tx {
+ bus_id = "uart0-tx";
+ cfg_hi = <0x4000>; /* 0x8 << 11 */
+ cfg_lo = <0>;
+ src_master = <0>;
+ dst_master = <1>;
+ };
+ spi0-tx {
+ bus_id = "spi0-tx";
+ cfg_hi = <0x2000>; /* 0x4 << 11 */
+ cfg_lo = <0>;
+ src_master = <0>;
+ dst_master = <0>;
+ };
+ };
};
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index c4b0eb3..9a7d084 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -1179,6 +1179,58 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
}
+bool dw_generic_filter(struct dma_chan *chan, void *param)
+{
+ struct dw_dma *dw = to_dw_dma(chan->device);
+ static struct dw_dma *last_dw;
+ static char *last_bus_id;
+ int found = 0, i = -1;
+
+ /*
+ * dmaengine framework calls this routine for all channels of all dma
+ * controller, until true is returned. If 'param' bus_id is not
+ * registered with a dma controller (dw), then there is no need of
+ * running below function for all channels of dw.
+ *
+ * This block of code does this by saving the parameters of last
+ * failure. If dw and param are same, i.e. trying on same dw with
+ * different channel, return false.
+ */
+ if (last_dw) {
+ if ((last_bus_id == param) && (last_dw == dw))
+ return false;
+ }
+
+ /*
+ * Return true:
+ * - If dw_dma's platform data is not filled with slave info, then all
+ * dma controllers are fine for transfer.
+ * - Or if param is NULL
+ */
+ if (!dw->sd || !param)
+ return true;
+
+ while (++i < dw->sd_count) {
+ if (!strcmp(dw->sd[i].bus_id, param)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ last_dw = dw;
+ last_bus_id = param;
+ return false;
+ }
+
+ chan->private = &dw->sd[i];
+ last_dw = NULL;
+ last_bus_id = NULL;
+
+ return true;
+}
+EXPORT_SYMBOL(dw_generic_filter);
+
/* --------------------- Cyclic DMA API extensions -------------------- */
/**
@@ -1462,6 +1514,96 @@ static void dw_dma_off(struct dw_dma *dw)
dw->chan[i].initialized = false;
}
+#ifdef CONFIG_OF
+static struct dw_dma_platform_data *
+__devinit dw_dma_parse_dt(struct platform_device *pdev)
+{
+ struct device_node *sn, *cn, *np = pdev->dev.of_node;
+ struct dw_dma_platform_data *pdata;
+ struct dw_dma_slave *sd;
+ u32 count, val, arr[4];
+
+ if (!np) {
+ dev_err(&pdev->dev, "Missing DT data\n");
+ return NULL;
+ }
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return NULL;
+
+ if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
+ return NULL;
+
+ if (of_property_read_bool(np, "is_private"))
+ pdata->is_private = true;
+
+ if (!of_property_read_u32(np, "chan_allocation_order",
+ &val))
+ pdata->chan_allocation_order = (unsigned char)val;
+
+ if (!of_property_read_u32(np, "chan_priority", &val))
+ pdata->chan_priority = (unsigned char)val;
+
+ if (!of_property_read_u32(np, "block_size", &val))
+ pdata->block_size = (unsigned short)val;
+
+ if (!of_property_read_u32(np, "nr_masters", &val)) {
+ if (val > 4)
+ return NULL;
+
+ pdata->nr_masters = (unsigned char)val;
+ }
+
+ if (!of_property_read_u32_array(np, "data_width", arr,
+ pdata->nr_masters))
+ for (count = 0; count < pdata->nr_masters; count++)
+ pdata->data_width[count] = arr[count];
+
+ /* parse slave data */
+ sn = of_find_node_by_name(np, "slave_info");
+ if (!sn)
+ return pdata;
+
+ count = 0;
+ /* calculate number of slaves */
+ for_each_child_of_node(sn, cn)
+ count++;
+
+ if (!count)
+ return NULL;
+
+ sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * count, GFP_KERNEL);
+ if (!sd)
+ return NULL;
+
+ count = 0;
+ for_each_child_of_node(sn, cn) {
+ of_property_read_string(cn, "bus_id", &sd[count].bus_id);
+ of_property_read_u32(cn, "cfg_hi", &sd[count].cfg_hi);
+ of_property_read_u32(cn, "cfg_lo", &sd[count].cfg_lo);
+ if (!of_property_read_u32(cn, "src_master", &val))
+ sd[count].src_master = (u8)val;
+
+ if (!of_property_read_u32(cn, "dst_master", &val))
+ sd[count].dst_master = (u8)val;
+
+ sd[count].dma_dev = &pdev->dev;
+ count++;
+ }
+
+ pdata->sd = sd;
+ pdata->sd_count = count;
+
+ return pdata;
+}
+#else
+static inline int dw_dma_parse_dt(struct platform_device *pdev)
+{
+ return -ENOSYS;
+}
+#endif
+
static int __devinit dw_probe(struct platform_device *pdev)
{
struct dw_dma_platform_data *pdata;
@@ -1478,6 +1620,9 @@ static int __devinit dw_probe(struct platform_device *pdev)
int i;
pdata = dev_get_platdata(&pdev->dev);
+ if (!pdata)
+ pdata = dw_dma_parse_dt(pdev);
+
if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS)
return -EINVAL;
@@ -1512,6 +1657,8 @@ static int __devinit dw_probe(struct platform_device *pdev)
clk_prepare_enable(dw->clk);
dw->regs = regs;
+ dw->sd = pdata->sd;
+ dw->sd_count = pdata->sd_count;
/* get hardware configuration parameters */
if (autocfg) {
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index ff39fa6..5cc61ba 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -231,6 +231,10 @@ struct dw_dma {
struct tasklet_struct tasklet;
struct clk *clk;
+ /* slave information */
+ struct dw_dma_slave *sd;
+ unsigned int sd_count;
+
u8 all_chan_mask;
/* hardware configuration */
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index 62a6190..4d1c8c3 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -15,6 +15,26 @@
#include <linux/dmaengine.h>
/**
+ * struct dw_dma_slave - Controller-specific information about a slave
+ *
+ * @dma_dev: required DMA master device. Depricated.
+ * @bus_id: name of this device channel, not just a device name since
+ * devices may have more than one channel e.g. "foo_tx"
+ * @cfg_hi: Platform-specific initializer for the CFG_HI register
+ * @cfg_lo: Platform-specific initializer for the CFG_LO register
+ * @src_master: src master for transfers on allocated channel.
+ * @dst_master: dest master for transfers on allocated channel.
+ */
+struct dw_dma_slave {
+ struct device *dma_dev;
+ const char *bus_id;
+ u32 cfg_hi;
+ u32 cfg_lo;
+ u8 src_master;
+ u8 dst_master;
+};
+
+/**
* struct dw_dma_platform_data - Controller configuration parameters
* @nr_channels: Number of channels supported by hardware (max 8)
* @is_private: The device channels should be marked as private and not for
@@ -25,6 +45,8 @@
* @nr_masters: Number of AHB masters supported by the controller
* @data_width: Maximum data width supported by hardware per AHB master
* (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
+ * @sd: slave specific data. Used for configuring channels
+ * @sd_count: count of slave data structures passed.
*/
struct dw_dma_platform_data {
unsigned int nr_channels;
@@ -38,6 +60,9 @@ struct dw_dma_platform_data {
unsigned short block_size;
unsigned char nr_masters;
unsigned char data_width[4];
+
+ struct dw_dma_slave *sd;
+ unsigned int sd_count;
};
/* bursts size */
@@ -52,23 +77,6 @@ enum dw_dma_msize {
DW_DMA_MSIZE_256,
};
-/**
- * struct dw_dma_slave - Controller-specific information about a slave
- *
- * @dma_dev: required DMA master device
- * @cfg_hi: Platform-specific initializer for the CFG_HI register
- * @cfg_lo: Platform-specific initializer for the CFG_LO register
- * @src_master: src master for transfers on allocated channel.
- * @dst_master: dest master for transfers on allocated channel.
- */
-struct dw_dma_slave {
- struct device *dma_dev;
- u32 cfg_hi;
- u32 cfg_lo;
- u8 src_master;
- u8 dst_master;
-};
-
/* Platform-configurable bits in CFG_HI */
#define DWC_CFGH_FCMODE (1 << 0)
#define DWC_CFGH_FIFO_MODE (1 << 1)
@@ -106,5 +114,6 @@ void dw_dma_cyclic_stop(struct dma_chan *chan);
dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan);
dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan);
+bool dw_generic_filter(struct dma_chan *chan, void *param);
#endif /* DW_DMAC_H */
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related
* [PATCH 1/3] dmaengine: dw_dmac: Update documentation style comments for dw_dma_platform_data
From: Viresh Kumar @ 2012-10-12 5:43 UTC (permalink / raw)
To: linux-arm-kernel
Documentation style comments were missing for few fields in struct
dw_dma_platform_data. Add these.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
include/linux/dw_dmac.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index e1c8c9e..62a6190 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -19,6 +19,8 @@
* @nr_channels: Number of channels supported by hardware (max 8)
* @is_private: The device channels should be marked as private and not for
* by the general purpose DMA channel allocator.
+ * @chan_allocation_order: Allocate channels starting from 0 or 7
+ * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0.
* @block_size: Maximum block size supported by the controller
* @nr_masters: Number of AHB masters supported by the controller
* @data_width: Maximum data width supported by hardware per AHB master
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related
* [PATCH] i2c: change the id to let the i2c device work
From: Mark Brown @ 2012-10-12 5:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5077A33E.4080801@atmel.com>
On Fri, Oct 12, 2012 at 12:57:34PM +0800, Bo Shen wrote:
> On 10/12/2012 12:40, Mark Brown wrote:
> >On Fri, Oct 12, 2012 at 10:34:18AM +0800, Bo Shen wrote:
> >>As the old method will use platform device id, change the id to
> >>let the i2c device work
> >What are "the old method" and new method? You're not explaining why
> >this is needed...
> Maybe use the 'legacy method' will be better (I am not sure). Now,
> the Linux kernel is transferring to device tree which doesn't use
> platform device id. So, change the id to let the legacy code work.
> May you understand.
No, this still makes no sense to me. This is clearly a non-DT device
registration, what does DT have to do with anything here? What is the
practical problem you are seeing in your system and how does this help
with it?
^ permalink raw reply
* [PATCH] i2c: change the id to let the i2c device work
From: Bo Shen @ 2012-10-12 4:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121012044042.GI11726@opensource.wolfsonmicro.com>
Hi Mark,
On 10/12/2012 12:40, Mark Brown wrote:
> On Fri, Oct 12, 2012 at 10:34:18AM +0800, Bo Shen wrote:
>> As the old method will use platform device id, change the id to
>> let the i2c device work
>
> What are "the old method" and new method? You're not explaining why
> this is needed...
Maybe use the 'legacy method' will be better (I am not sure). Now, the
Linux kernel is transferring to device tree which doesn't use platform
device id. So, change the id to let the legacy code work.
May you understand.
>
>> static struct platform_device at91sam9260_twi_device = {
>> .name = "i2c-gpio",
>> - .id = -1,
>> + .id = 0,
>> .dev.platform_data = &pdata,
>
> This looks like a regression, if there's only one of a given type of
> device in the system it should have no numeric ID in the display name so
> having -1 is appropriate.
>
^ permalink raw reply
* [PATCH] ARM:IMX6Q:use pll2_pfd2_396m as the enfc_sel's parent
From: Mike Turquette @ 2012-10-12 4:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20120919134426.GA2450@S2101-09.ap.freescale.net>
On Wed, Sep 19, 2012 at 6:44 AM, Shawn Guo <shawn.guo@linaro.org> wrote:
> On Wed, Sep 19, 2012 at 09:31:30AM +0200, Sascha Hauer wrote:
>> On Wed, Sep 19, 2012 at 01:33:50PM +0800, Shawn Guo wrote:
>> > On Mon, Sep 10, 2012 at 03:17:56PM +0800, Huang Shijie wrote:
>> > > The gpmi-nand driver can support the ONFI nand chip's EDO (extra data out)
>> > > mode in the asynchrounous mode. In the asynchrounous mode 5, the gpmi
>> > > needs 100MHz clock for the IO. But with the pll2_pfd0_352m, we can not
>> > > get the 100MHz clock.
>> > >
>> > > So choose pll2_pfd2_396m as enfc_sel's parent.
>> > >
>> > > Signed-off-by: Huang Shijie <b32955@freescale.com>
>> >
>> > Applied, thanks.
>> >
>> > But we really expect that clock framework can get improved to have such
>> > case handled in clk_set_rate() call.
>>
>> How do you want to archieve that?
>
> Actually, I'm relying on Mike for that, as he said a patch for that
> is under hacking [1].
>
Hmm, I need to re-prioritize rebasing this patch...
>> It would be possible to teach the
>> clock framework to iterate over the possible parents and see what gives
>> the best result, but how do we teach the clock framework that there are
>> other constraints, like for example 'use this clock in low power mode
>> and that one otherwise'?
>>
> I have no idea, and I'm not even sure Mike's patch will address such
> constraints. Mike?
>
I'm not sure about the "low power clock configuration" case, but I
have some local code for the OMAP clock port which is in a "clk-sets"
branch. This code looks at requested clock rates and matches them to
a table which affects many clocks. Essentially the idea is that an
operating point (OPP) is a combination of both voltage for a rail and
a snapshot of clock configuration for many clocks in a subtree.
Instead of relying on the algorithmic methods for programming a clock
rate (such as in the clk-divider.c implementation or the many
platform-specific PLL .set_rate implementations) this implementation
uses a limited set of predefined allowed clock rates and somewhat
simplifies the concept of programming many clocks for predefined
use-cases. Unfortunately the code is in terrible shape and not ready
for public review, but I will prioritize it. This code goes along
nicely with my next crack at solving the generic DVFS problem.
This approach might help the "low power clock configuration" case, but
time will only tell. I will take into consideration not only a table
listing valid frequencies, but also valid parents which should help
your case.
Regards,
Mike
> Shawn
>
>> We have a similar problem with the IPU: When the LDB is used, the IPU
>> pixel clock has to be switched to the LDB clock, even if other clocks
>> would result in a more accurate frequency.
>>
>> That's a topic for a long long discussion, I think even longer than it
>> took to introduce the clock framework ;)
>>
>
> [1] http://thread.gmane.org/gmane.linux.ports.tegra/6196/focus=6198
^ permalink raw reply
* [PATCH] i2c: change the id to let the i2c device work
From: Mark Brown @ 2012-10-12 4:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350009258-10044-1-git-send-email-voice.shen@atmel.com>
On Fri, Oct 12, 2012 at 10:34:18AM +0800, Bo Shen wrote:
> As the old method will use platform device id, change the id to
> let the i2c device work
What are "the old method" and new method? You're not explaining why
this is needed...
> static struct platform_device at91sam9260_twi_device = {
> .name = "i2c-gpio",
> - .id = -1,
> + .id = 0,
> .dev.platform_data = &pdata,
This looks like a regression, if there's only one of a given type of
device in the system it should have no numeric ID in the display name so
having -1 is appropriate.
^ permalink raw reply
* [PATCH 07/11] fsmc/nand: Provide contiguous buffers to dma
From: Vipin Kumar @ 2012-10-12 3:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdYjA8QUh4HqvE1rsnXcGA4WafTkMq_wLNJ__gXEnEYrow@mail.gmail.com>
On 10/11/2012 9:36 PM, Linus Walleij wrote:
> On Thu, Oct 11, 2012 at 6:15 AM, viresh kumar<viresh.kumar@linaro.org> wrote:
>> On Wed, Oct 10, 2012 at 10:37 PM, Linus Walleij
>> <linus.walleij@linaro.org> wrote:
>
>>> dma_sync_single_for_device() is translating the virtual
>>> address to physical for every chunk BTW.
>>
>> I pray that i am wrong here, otherwise i would be thrown out from
>> the maintainers list for this driver :)
>>
>> dma_sync_single_for_device() is not doing anything on the buffer, but
>> on the LLI item. Actually it is flushing LLI struct so that DMA h/w can get
>> the correct values.
>
> Sorry no, I'm the one who's wrong...
>
> So the DMA engine memcpy() is not mapping virt->phys
> but expects physical addresses to be provided.
>
> So dma_map_single() needs to be called on the stuff
> passed in to dev->device_prep_dma_memcpy().
>
> And currently there is indeed a dma_map_single() in
> dma_xfer() in fsmc_nand.c which should work just fine.
>
> dma_map_single() will only work if the buffer is
> physically contiguous.
>
> And the block layer of the subsystem should take care
> of only handing the driver buffers that are contiguous
> I think? Not that I'm an expert here ... more some
> guesswork :-/
The buffers provided to the driver are actually user buffers. The reason
I say that is because the generic nand test modules eg
drivers/mtd/nand/mtd_stresstest.c calls mtd->_read with a user buffer as
an argument
This same buffer directly trickles down to the driver
Artem, should we clearly cast this buffer as a user pointer instead of
just a 'uint8_t *'.
Regards
Vipin
^ permalink raw reply
* [PATCH 3/7] ARM: tegra30: cpuidle: add LP2 driver for secondary CPUs
From: Joseph Lo @ 2012-10-12 3:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5076F2AE.6030509@wwwdotorg.org>
On Fri, 2012-10-12 at 00:24 +0800, Stephen Warren wrote:
> On 10/11/2012 03:15 AM, Joseph Lo wrote:
> > On Wed, 2012-10-10 at 06:38 +0800, Stephen Warren wrote:
> >> On 10/08/2012 04:26 AM, Joseph Lo wrote:
> >>> This supports power-gated (LP2) idle on secondary CPUs for Tegra30.
> >>> The secondary CPUs can go into LP2 state independently. When CPU goes
> >>> into LP2 state, it saves it's state and puts itself to flow controlled
> >>> WFI state. After that, it will been power gated.
> >>
> >>> diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
> >>
> >>> +void __cpuinit tegra_clear_cpu_in_lp2(int cpu)
> >>> +{
> >>> + spin_lock(&tegra_lp2_lock);
> >>> + BUG_ON(!cpumask_test_cpu(cpu, &tegra_in_lp2));
> >>> + cpumask_clear_cpu(cpu, &tegra_in_lp2);
> >>> +
> >>> + /*
> >>> + * Update the IRAM copy used by the reset handler. The IRAM copy
> >>> + * can't use used directly by cpumask_clear_cpu() because it uses
> >>> + * LDREX/STREX which requires the addressed location to be inner
> >>> + * cacheable and sharable which IRAM isn't.
> >>> + */
> >>> + writel(tegra_in_lp2.bits[0], tegra_cpu_lp2_mask);
> >>> + dsb();
> >>
> >> Why not /just/ store the data in IRAM, and read/write directly to it,
> >> rather than maintaining an SDRAM-based copy of it?
> >>
> >> Then, wouldn't the body of this function be simply:
> >>
> >> spin_lock();
> >> BUG_ON(!(tegra_cpu_lp2_mask & BIT(cpu)));
> >> tegra_cpu_lp2_mask |= BIT(cpu);
> >> spin_unlock();
> >>
> >
> > It may not simple like this. To maintain it identical to a cpumask. It
> > may look likes below. Because I need to compare it with cpu_online_mask.
>
> Oh, the comparison against cpu_online_mask() is what I was missing. I
> guess that offline CPUs don't go into LP2, so you can't just check that
> tegra_cpu_lp2_mask == (1 << num_cpus()) - 1.
>
> One way to avoid that might be to maintain a cpu_in_lp2_count variable
> alongside the mask, and simply compare that against num_online_cpus()
> rather than comparing the two masks. At least that would avoid the
> following line:
>
> >>> + writel(tegra_in_lp2.bits[0], tegra_cpu_lp2_mask);
>
> ... making use of knowledge of the internal structure of the struct
> cpumask type.
>
> However, given the comparison requirement, either way is probably fine.
OK. I got your idea now. And I rechecked it today. The method that you
suggested original could satisfy the usage here. It could maintain the
CPUs go into LP2 as a cpumask. I just verified it. Will update in next
version.
Thanks,
Joseph
^ permalink raw reply
* [PATCH] i2c: change the id to let the i2c device work
From: Bo Shen @ 2012-10-12 2:34 UTC (permalink / raw)
To: linux-arm-kernel
As the old method will use platform device id, change the id to
let the i2c device work
Signed-off-by: Bo Shen <voice.shen@atmel.com>
---
arch/arm/mach-at91/at91sam9260_devices.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 5c5966a..aad76b7 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -471,7 +471,7 @@ static struct i2c_gpio_platform_data pdata = {
static struct platform_device at91sam9260_twi_device = {
.name = "i2c-gpio",
- .id = -1,
+ .id = 0,
.dev.platform_data = &pdata,
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 1/5] [media] omap3isp: Fix compilation error in ispreg.h
From: Laurent Pinchart @ 2012-10-12 1:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121007101718.073aed3b@infradead.org>
Hi Mauro,
On Sunday 07 October 2012 10:17:18 Mauro Carvalho Chehab wrote:
> Em Tue, 2 Oct 2012 09:31:58 -0700 Tony Lindgren escreveu:
> > * Ido Yariv <ido@wizery.com> [121001 15:48]:
> > > Commit c49f34bc ("ARM: OMAP2+ Move SoC specific headers to be local to
> > > mach-omap2") moved omap34xx.h to mach-omap2. This broke omap3isp, as it
> > > includes omap34xx.h.
> > >
> > > Instead of moving omap34xx to platform_data, simply add the two
> > > definitions the driver needs and remove the include altogether.
> > >
> > > Signed-off-by: Ido Yariv <ido@wizery.com>
> >
> > I'm assuming that Mauro picks this one up, sorry
> > for breaking it.
>
> Picked, thanks.
>
> With regards to the other patches in this series, IMHO, it
> makes more sense to go through arm omap tree, so, for the
> patches on this series that touch at drivers/media/platform/*:
>
> Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
>
> > Acked-by: Tony Lindgren <tony@atomide.com>
> >
> > > ---
> > >
> > > drivers/media/platform/omap3isp/ispreg.h | 6 +++---
> > > 1 file changed, 3 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/media/platform/omap3isp/ispreg.h
> > > b/drivers/media/platform/omap3isp/ispreg.h index 084ea77..e2c57f3
> > > 100644
> > > --- a/drivers/media/platform/omap3isp/ispreg.h
> > > +++ b/drivers/media/platform/omap3isp/ispreg.h
> > > @@ -27,13 +27,13 @@
> > >
> > > #ifndef OMAP3_ISP_REG_H
> > > #define OMAP3_ISP_REG_H
> > >
> > > -#include <plat/omap34xx.h>
> > > -
> > > -
> > >
> > > #define CM_CAM_MCLK_HZ 172800000 /* Hz */
> > >
> > > /* ISP Submodules offset */
> > >
> > > +#define L4_34XX_BASE 0x48000000
> > > +#define OMAP3430_ISP_BASE (L4_34XX_BASE + 0xBC000)
> > > +
> > >
> > > #define OMAP3ISP_REG_BASE OMAP3430_ISP_BASE
> > > #define OMAP3ISP_REG(offset) (OMAP3ISP_REG_BASE + (offset))
I'll send a follow-up patch that removes all those definitions as they're
actually not needed.
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [PATCH v3 6/6] arm/dts: OMAP3/4: Add iommu nodes
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350003977-32744-1-git-send-email-omar.luna@linaro.org>
Add nodes for iommu DT, to interface with hwmods.
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/boot/dts/omap3.dtsi | 12 +++++++++++-
arch/arm/boot/dts/omap4.dtsi | 17 ++++++++++++++++-
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index f38ea87..c76872e 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -37,12 +37,17 @@
};
iva {
- compatible = "ti,iva2.2";
+ compatible = "ti,iva2.2", "simple-bus";
ti,hwmods = "iva";
dsp {
compatible = "ti,omap3-c64";
};
+
+ mmu_iva: mmu_iva at 5d000000 {
+ compatible = "ti,omap3-iommu";
+ ti,hwmods = "mmu_iva";
+ };
};
};
@@ -227,6 +232,11 @@
ti,hwmods = "mmc3";
};
+ mmu_isp: mmu_isp at 480bd400 {
+ compatible = "ti,omap3-iommu";
+ ti,hwmods = "mmu_isp";
+ };
+
wdt2: wdt at 48314000 {
compatible = "ti,omap3-wdt";
ti,hwmods = "wd_timer2";
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 3883f94..f084418 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -71,8 +71,23 @@
};
dsp {
- compatible = "ti,omap3-c64";
+ compatible = "ti,omap3-c64", "simple-bus";
ti,hwmods = "dsp";
+
+ mmu_dsp: mmu_dsp at 4a066000 {
+ compatible = "ti,omap4-iommu";
+ ti,hwmods = "mmu_dsp";
+ };
+ };
+
+ ipu {
+ compatible = "ti,omap4-ipu", "simple-bus";
+ ti,hwmods = "ipu";
+
+ mmu_ipu: mmu_ipu at 55082000 {
+ compatible = "ti,omap4-iommu";
+ ti,hwmods = "mmu_ipu";
+ };
};
iva {
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 5/6] ARM: OMAP: iommu: add device tree support
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350003977-32744-1-git-send-email-omar.luna@linaro.org>
Adapt driver to use DT if provided.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
.../devicetree/bindings/arm/omap/iommu.txt | 10 +++
arch/arm/mach-omap2/omap-iommu.c | 4 ++
drivers/iommu/omap-iommu.c | 65 +++++++++++++++++++-
3 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/arm/omap/iommu.txt
diff --git a/Documentation/devicetree/bindings/arm/omap/iommu.txt b/Documentation/devicetree/bindings/arm/omap/iommu.txt
new file mode 100644
index 0000000..2bb780f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/iommu.txt
@@ -0,0 +1,10 @@
+* MMU (Memory Management Unit)
+
+MMU present in OMAP subsystems.
+
+Required properties:
+ compatible : should be "ti,omap3-iommu" for OMAP3 MMUs
+ compatible : should be "ti,omap4-iommu" for OMAP4 MMUs
+
+Optional properties:
+ None
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index 82a422a..4d6145d 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/slab.h>
@@ -29,6 +30,9 @@ static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
struct omap_mmu_dev_attr *a = (struct omap_mmu_dev_attr *)oh->dev_attr;
static int i;
+ if (of_have_populated_dt())
+ return 0;
+
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index e266ad7..946366f 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -21,12 +21,15 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/pm_runtime.h>
+#include <linux/of.h>
#include <asm/cacheflush.h>
#include <plat/iommu.h>
#include <plat/iopgtable.h>
+#include <plat/omap_device.h>
+#include <plat/omap_hwmod.h>
#define for_each_iotlb_cr(obj, n, __i, cr) \
for (__i = 0; \
@@ -916,13 +919,63 @@ static void omap_iommu_detach(struct omap_iommu *obj)
/*
* OMAP Device MMU(IOMMU) detection
*/
+static int __devinit
+iommu_add_platform_data_from_dt(struct platform_device *pdev)
+{
+ struct iommu_platform_data *pdata;
+ struct device_node *node = pdev->dev.of_node;
+ struct omap_hwmod *oh;
+ struct omap_mmu_dev_attr *a;
+ int ret = 0;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ of_property_read_string(node, "ti,hwmods", &pdata->name);
+ oh = omap_hwmod_lookup(pdata->name);
+ if (!oh) {
+ dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n", pdata->name);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ a = (struct omap_mmu_dev_attr *)oh->dev_attr;
+ pdata->nr_tlb_entries = a->nr_tlb_entries;
+ pdata->da_start = a->da_start;
+ pdata->da_end = a->da_end;
+
+ if (oh->rst_lines_cnt == 1) {
+ pdata->reset_name = oh->rst_lines->name;
+ pdata->assert_reset = omap_device_assert_hardreset;
+ pdata->deassert_reset = omap_device_deassert_hardreset;
+ }
+
+ ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+ if (ret)
+ dev_err(&pdev->dev, "Cannot add pdata for %s\n", pdata->name);
+
+out:
+ kfree(pdata);
+
+ return ret;
+}
+
static int __devinit omap_iommu_probe(struct platform_device *pdev)
{
int err = -ENODEV;
int irq;
struct omap_iommu *obj;
struct resource *res;
- struct iommu_platform_data *pdata = pdev->dev.platform_data;
+ struct iommu_platform_data *pdata;
+
+ if (of_have_populated_dt()) {
+ err = iommu_add_platform_data_from_dt(pdev);
+ if (err)
+ return err;
+ }
+
+ pdata = pdev->dev.platform_data;
obj = kzalloc(sizeof(*obj), GFP_KERNEL);
if (!obj)
@@ -1031,12 +1084,22 @@ static const struct dev_pm_ops iommu_pm_ops = {
NULL)
};
+#if defined(CONFIG_OF)
+static const struct of_device_id omap_iommu_of_match[] = {
+ { .compatible = "ti,omap3-iommu" },
+ { .compatible = "ti,omap4-iommu" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, omap_iommu_of_match);
+#endif
+
static struct platform_driver omap_iommu_driver = {
.probe = omap_iommu_probe,
.remove = __devexit_p(omap_iommu_remove),
.driver = {
.name = "omap-iommu",
.pm = &iommu_pm_ops,
+ .of_match_table = of_match_ptr(omap_iommu_of_match),
},
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH 4/6] ARM: OMAP: iommu: optimize save and restore routines
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350003977-32744-1-git-send-email-omar.luna@linaro.org>
These functions save and restore registers irrespectively of their
read or write permissions, this ends up in registers being saved
that can't be restored because of read only attributes. OTOH, so
far only 3 of them need to be saved.
In future GP_REG (which is present only on OMAP4 ipu) needs to be
saved but right now there is no API that can alter its value. Also,
protected TLB entries must be saved but this can be in a separate
patch as the original code didn't implement the loop to traverse
protected TLB entries.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/mach-omap2/iommu2.c | 38 ++++++++++++++----------------
arch/arm/plat-omap/include/plat/iommu.h | 10 +++++++-
arch/arm/plat-omap/include/plat/iommu2.h | 2 --
drivers/iommu/omap-iommu.c | 3 +--
4 files changed, 28 insertions(+), 25 deletions(-)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 3e47786..cd77abb 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -19,6 +19,7 @@
#include <linux/stringify.h>
#include <plat/iommu.h>
+#include <plat/omap-pm.h>
/*
* omap2 architecture specific register bit definitions
@@ -55,20 +56,26 @@
static void __iommu_set_twl(struct omap_iommu *obj, bool on)
{
- u32 l = iommu_read_reg(obj, MMU_CNTL);
+ u32 l;
if (on)
- iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE);
+ l = MMU_IRQ_TWL_MASK;
else
- iommu_write_reg(obj, MMU_IRQ_TLB_MISS_MASK, MMU_IRQENABLE);
+ l = MMU_IRQ_TLB_MISS_MASK;
+
+ iommu_write_reg(obj, l, MMU_IRQENABLE);
+ obj->context.irqen = l;
+ l = iommu_read_reg(obj, MMU_CNTL);
l &= ~MMU_CNTL_MASK;
+
if (on)
l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
else
l |= (MMU_CNTL_MMU_EN);
iommu_write_reg(obj, l, MMU_CNTL);
+ obj->context.cntl = l;
}
@@ -88,6 +95,7 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
(l >> 4) & 0xf, l & 0xf);
iommu_write_reg(obj, pa, MMU_TTB);
+ obj->context.ttb = pa;
__iommu_set_twl(obj, true);
@@ -100,6 +108,7 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
l &= ~MMU_CNTL_MASK;
iommu_write_reg(obj, l, MMU_CNTL);
+ obj->context.cntl = l;
dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
}
@@ -249,28 +258,17 @@ out:
static void omap2_iommu_save_ctx(struct omap_iommu *obj)
{
- int i;
- u32 *p = obj->ctx;
-
- for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
- p[i] = iommu_read_reg(obj, i * sizeof(u32));
- dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
- }
-
- BUG_ON(p[0] != IOMMU_ARCH_VERSION);
+ obj->ctx_loss_cnt = omap_pm_get_dev_context_loss_count(obj->dev);
}
static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
{
- int i;
- u32 *p = obj->ctx;
-
- for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
- iommu_write_reg(obj, p[i], i * sizeof(u32));
- dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
- }
+ if (omap_pm_get_dev_context_loss_count(obj->dev) == obj->ctx_loss_cnt)
+ return;
- BUG_ON(p[0] != IOMMU_ARCH_VERSION);
+ iommu_write_reg(obj, obj->context.ttb, MMU_TTB);
+ iommu_write_reg(obj, obj->context.irqen, MMU_IRQENABLE);
+ iommu_write_reg(obj, obj->context.cntl, MMU_CNTL);
}
static void omap2_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 902d193..af14486 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -27,6 +27,13 @@ struct iotlb_entry {
};
};
+/* context registers */
+struct iommu_regs {
+ u32 irqen;
+ u32 cntl;
+ u32 ttb;
+};
+
struct omap_iommu {
const char *name;
struct module *owner;
@@ -50,7 +57,8 @@ struct omap_iommu {
struct list_head mmap;
struct mutex mmap_lock; /* protect mmap */
- void *ctx; /* iommu context: registres saved area */
+ struct iommu_regs context;
+ int ctx_loss_cnt;
u32 da_start;
u32 da_end;
};
diff --git a/arch/arm/plat-omap/include/plat/iommu2.h b/arch/arm/plat-omap/include/plat/iommu2.h
index 1579694..bc43d41 100644
--- a/arch/arm/plat-omap/include/plat/iommu2.h
+++ b/arch/arm/plat-omap/include/plat/iommu2.h
@@ -35,8 +35,6 @@
#define MMU_READ_RAM 0x6c
#define MMU_EMU_FAULT_AD 0x70
-#define MMU_REG_SIZE 256
-
/*
* MMU Register bit definitions
*/
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 875e894..e266ad7 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -924,14 +924,13 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
struct resource *res;
struct iommu_platform_data *pdata = pdev->dev.platform_data;
- obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
+ obj = kzalloc(sizeof(*obj), GFP_KERNEL);
if (!obj)
return -ENOMEM;
obj->nr_tlb_entries = pdata->nr_tlb_entries;
obj->name = pdata->name;
obj->dev = &pdev->dev;
- obj->ctx = (void *)obj + sizeof(*obj);
obj->da_start = pdata->da_start;
obj->da_end = pdata->da_end;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 4/6] ARM: OMAP: iommu: optimize save and restore routines
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350003977-32744-1-git-send-email-omar.luna@linaro.org>
These functions save and restore registers irrespectively of their
read or write permissions, this ends up in registers being saved
that can't be restored because of read only attributes. OTOH, so
far only 3 of them need to be saved.
In future GP_REG (which is present only on OMAP4 ipu) needs to be
saved but right now there is no API that can alter its value. Also,
protected TLB entries must be saved but this can be in a separate
patch as the original code didn't implement the loop to traverse
protected TLB entries.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/mach-omap2/iommu2.c | 38 ++++++++++++++----------------
arch/arm/plat-omap/include/plat/iommu.h | 10 +++++++-
arch/arm/plat-omap/include/plat/iommu2.h | 2 --
drivers/iommu/omap-iommu.c | 3 +--
4 files changed, 28 insertions(+), 25 deletions(-)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 3e47786..cd77abb 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -19,6 +19,7 @@
#include <linux/stringify.h>
#include <plat/iommu.h>
+#include <plat/omap-pm.h>
/*
* omap2 architecture specific register bit definitions
@@ -55,20 +56,26 @@
static void __iommu_set_twl(struct omap_iommu *obj, bool on)
{
- u32 l = iommu_read_reg(obj, MMU_CNTL);
+ u32 l;
if (on)
- iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE);
+ l = MMU_IRQ_TWL_MASK;
else
- iommu_write_reg(obj, MMU_IRQ_TLB_MISS_MASK, MMU_IRQENABLE);
+ l = MMU_IRQ_TLB_MISS_MASK;
+
+ iommu_write_reg(obj, l, MMU_IRQENABLE);
+ obj->context.irqen = l;
+ l = iommu_read_reg(obj, MMU_CNTL);
l &= ~MMU_CNTL_MASK;
+
if (on)
l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
else
l |= (MMU_CNTL_MMU_EN);
iommu_write_reg(obj, l, MMU_CNTL);
+ obj->context.cntl = l;
}
@@ -88,6 +95,7 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
(l >> 4) & 0xf, l & 0xf);
iommu_write_reg(obj, pa, MMU_TTB);
+ obj->context.ttb = pa;
__iommu_set_twl(obj, true);
@@ -100,6 +108,7 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
l &= ~MMU_CNTL_MASK;
iommu_write_reg(obj, l, MMU_CNTL);
+ obj->context.cntl = l;
dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
}
@@ -249,28 +258,17 @@ out:
static void omap2_iommu_save_ctx(struct omap_iommu *obj)
{
- int i;
- u32 *p = obj->ctx;
-
- for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
- p[i] = iommu_read_reg(obj, i * sizeof(u32));
- dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
- }
-
- BUG_ON(p[0] != IOMMU_ARCH_VERSION);
+ obj->ctx_loss_cnt = omap_pm_get_dev_context_loss_count(obj->dev);
}
static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
{
- int i;
- u32 *p = obj->ctx;
-
- for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
- iommu_write_reg(obj, p[i], i * sizeof(u32));
- dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
- }
+ if (omap_pm_get_dev_context_loss_count(obj->dev) == obj->ctx_loss_cnt)
+ return;
- BUG_ON(p[0] != IOMMU_ARCH_VERSION);
+ iommu_write_reg(obj, obj->context.ttb, MMU_TTB);
+ iommu_write_reg(obj, obj->context.irqen, MMU_IRQENABLE);
+ iommu_write_reg(obj, obj->context.cntl, MMU_CNTL);
}
static void omap2_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 902d193..af14486 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -27,6 +27,13 @@ struct iotlb_entry {
};
};
+/* context registers */
+struct iommu_regs {
+ u32 irqen;
+ u32 cntl;
+ u32 ttb;
+};
+
struct omap_iommu {
const char *name;
struct module *owner;
@@ -50,7 +57,8 @@ struct omap_iommu {
struct list_head mmap;
struct mutex mmap_lock; /* protect mmap */
- void *ctx; /* iommu context: registres saved area */
+ struct iommu_regs context;
+ int ctx_loss_cnt;
u32 da_start;
u32 da_end;
};
diff --git a/arch/arm/plat-omap/include/plat/iommu2.h b/arch/arm/plat-omap/include/plat/iommu2.h
index 1579694..bc43d41 100644
--- a/arch/arm/plat-omap/include/plat/iommu2.h
+++ b/arch/arm/plat-omap/include/plat/iommu2.h
@@ -35,8 +35,6 @@
#define MMU_READ_RAM 0x6c
#define MMU_EMU_FAULT_AD 0x70
-#define MMU_REG_SIZE 256
-
/*
* MMU Register bit definitions
*/
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 875e894..e266ad7 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -924,14 +924,13 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
struct resource *res;
struct iommu_platform_data *pdata = pdev->dev.platform_data;
- obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
+ obj = kzalloc(sizeof(*obj), GFP_KERNEL);
if (!obj)
return -ENOMEM;
obj->nr_tlb_entries = pdata->nr_tlb_entries;
obj->name = pdata->name;
obj->dev = &pdev->dev;
- obj->ctx = (void *)obj + sizeof(*obj);
obj->da_start = pdata->da_start;
obj->da_end = pdata->da_end;
--
1.7.9.5
^ permalink raw reply related
* [PATCH 3/6] ARM: OMAP: iommu: pm runtime save and restore context
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350003977-32744-1-git-send-email-omar.luna@linaro.org>
Save and restore context during pm runtime transitions.
For now, the previous API for this purpose will trigger
pm runtime functions, and will be left as exported symbol
for compatibility with it's only user.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
drivers/iommu/omap-iommu.c | 29 +++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 37644c4..875e894 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -97,7 +97,7 @@ void omap_iommu_save_ctx(struct device *dev)
{
struct omap_iommu *obj = dev_to_omap_iommu(dev);
- arch_iommu->save_ctx(obj);
+ pm_runtime_put_sync(obj->dev);
}
EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
@@ -109,7 +109,7 @@ void omap_iommu_restore_ctx(struct device *dev)
{
struct omap_iommu *obj = dev_to_omap_iommu(dev);
- arch_iommu->restore_ctx(obj);
+ pm_runtime_get_sync(obj->dev);
}
EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
@@ -1008,11 +1008,36 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
return 0;
}
+static int omap_iommu_runtime_suspend(struct device *dev)
+{
+ struct omap_iommu *obj = to_iommu(dev);
+
+ arch_iommu->save_ctx(obj);
+
+ return 0;
+}
+
+static int omap_iommu_runtime_resume(struct device *dev)
+{
+ struct omap_iommu *obj = to_iommu(dev);
+
+ arch_iommu->restore_ctx(obj);
+
+ return 0;
+}
+
+static const struct dev_pm_ops iommu_pm_ops = {
+ SET_RUNTIME_PM_OPS(omap_iommu_runtime_suspend,
+ omap_iommu_runtime_resume,
+ NULL)
+};
+
static struct platform_driver omap_iommu_driver = {
.probe = omap_iommu_probe,
.remove = __devexit_p(omap_iommu_remove),
.driver = {
.name = "omap-iommu",
+ .pm = &iommu_pm_ops,
},
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 3/6] ARM: OMAP: iommu: pm runtime save and restore context
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350003977-32744-1-git-send-email-omar.luna@linaro.org>
Save and restore context during pm runtime transitions.
For now, the previous API for this purpose will trigger
pm runtime functions, and will be left as exported symbol
for compatibility with it's only user.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
drivers/iommu/omap-iommu.c | 29 +++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 37644c4..875e894 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -97,7 +97,7 @@ void omap_iommu_save_ctx(struct device *dev)
{
struct omap_iommu *obj = dev_to_omap_iommu(dev);
- arch_iommu->save_ctx(obj);
+ pm_runtime_put_sync(obj->dev);
}
EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
@@ -109,7 +109,7 @@ void omap_iommu_restore_ctx(struct device *dev)
{
struct omap_iommu *obj = dev_to_omap_iommu(dev);
- arch_iommu->restore_ctx(obj);
+ pm_runtime_get_sync(obj->dev);
}
EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
@@ -1008,11 +1008,36 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
return 0;
}
+static int omap_iommu_runtime_suspend(struct device *dev)
+{
+ struct omap_iommu *obj = to_iommu(dev);
+
+ arch_iommu->save_ctx(obj);
+
+ return 0;
+}
+
+static int omap_iommu_runtime_resume(struct device *dev)
+{
+ struct omap_iommu *obj = to_iommu(dev);
+
+ arch_iommu->restore_ctx(obj);
+
+ return 0;
+}
+
+static const struct dev_pm_ops iommu_pm_ops = {
+ SET_RUNTIME_PM_OPS(omap_iommu_runtime_suspend,
+ omap_iommu_runtime_resume,
+ NULL)
+};
+
static struct platform_driver omap_iommu_driver = {
.probe = omap_iommu_probe,
.remove = __devexit_p(omap_iommu_remove),
.driver = {
.name = "omap-iommu",
+ .pm = &iommu_pm_ops,
},
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350003977-32744-1-git-send-email-omar.luna@linaro.org>
Use runtime PM functionality interfaced with hwmod enable/idle
functions, to replace direct clock operations and sysconfig
handling.
Dues to reset sequence, pm_runtime_put_sync must be used, to avoid
possible operations with the module under reset.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/mach-omap2/iommu2.c | 17 -----------
arch/arm/mach-omap2/omap-iommu.c | 1 -
arch/arm/plat-omap/include/plat/iommu.h | 2 --
arch/arm/plat-omap/include/plat/iommu2.h | 2 --
drivers/iommu/omap-iommu.c | 45 +++++++++++++-----------------
5 files changed, 19 insertions(+), 48 deletions(-)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 35cab47..3e47786 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -25,15 +25,6 @@
*/
#define IOMMU_ARCH_VERSION 0x00000011
-/* SYSCONF */
-#define MMU_SYS_IDLE_SHIFT 3
-#define MMU_SYS_IDLE_FORCE (0 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_NONE (1 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT)
-
-#define MMU_SYS_AUTOIDLE 1
-
/* IRQSTATUS & IRQENABLE */
#define MMU_IRQ_MULTIHITFAULT (1 << 4)
#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
@@ -96,11 +87,6 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
(l >> 4) & 0xf, l & 0xf);
- l = iommu_read_reg(obj, MMU_SYSCONFIG);
- l &= ~MMU_SYS_IDLE_MASK;
- l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
- iommu_write_reg(obj, l, MMU_SYSCONFIG);
-
iommu_write_reg(obj, pa, MMU_TTB);
__iommu_set_twl(obj, true);
@@ -114,7 +100,6 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
l &= ~MMU_CNTL_MASK;
iommu_write_reg(obj, l, MMU_CNTL);
- iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG);
dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
}
@@ -243,8 +228,6 @@ omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
char *p = buf;
pr_reg(REVISION);
- pr_reg(SYSCONFIG);
- pr_reg(SYSSTATUS);
pr_reg(IRQSTATUS);
pr_reg(IRQENABLE);
pr_reg(WALKING_ST);
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index e400845..82a422a 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -34,7 +34,6 @@ static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
return -ENOMEM;
pdata->name = oh->name;
- pdata->clk_name = oh->main_clk;
pdata->nr_tlb_entries = a->nr_tlb_entries;
pdata->da_start = a->da_start;
pdata->da_end = a->da_end;
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 0fa913d..902d193 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -30,7 +30,6 @@ struct iotlb_entry {
struct omap_iommu {
const char *name;
struct module *owner;
- struct clk *clk;
void __iomem *regbase;
struct device *dev;
void *isr_priv;
@@ -120,7 +119,6 @@ struct omap_mmu_dev_attr {
struct iommu_platform_data {
const char *name;
- const char *clk_name;
const char *reset_name;
int nr_tlb_entries;
u32 da_start;
diff --git a/arch/arm/plat-omap/include/plat/iommu2.h b/arch/arm/plat-omap/include/plat/iommu2.h
index d4116b5..1579694 100644
--- a/arch/arm/plat-omap/include/plat/iommu2.h
+++ b/arch/arm/plat-omap/include/plat/iommu2.h
@@ -19,8 +19,6 @@
* MMU Register offsets
*/
#define MMU_REVISION 0x00
-#define MMU_SYSCONFIG 0x10
-#define MMU_SYSSTATUS 0x14
#define MMU_IRQSTATUS 0x18
#define MMU_IRQENABLE 0x1c
#define MMU_WALKING_ST 0x40
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index c1caee4..37644c4 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -16,11 +16,11 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
-#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/iommu.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
#include <asm/cacheflush.h>
@@ -142,11 +142,10 @@ static int iommu_enable(struct omap_iommu *obj)
}
}
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
err = arch_iommu->enable(obj);
- clk_disable(obj->clk);
return err;
}
@@ -158,11 +157,9 @@ static void iommu_disable(struct omap_iommu *obj)
if (!obj || !pdata)
return;
- clk_enable(obj->clk);
-
arch_iommu->disable(obj);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
if (pdata->assert_reset)
pdata->assert_reset(pdev, pdata->reset_name);
@@ -288,7 +285,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
if (!obj || !obj->nr_tlb_entries || !e)
return -EINVAL;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
iotlb_lock_get(obj, &l);
if (l.base == obj->nr_tlb_entries) {
@@ -318,7 +315,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
cr = iotlb_alloc_cr(obj, e);
if (IS_ERR(cr)) {
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return PTR_ERR(cr);
}
@@ -332,7 +329,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
l.vict = l.base;
iotlb_lock_set(obj, &l);
out:
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return err;
}
@@ -362,7 +359,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
int i;
struct cr_regs cr;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
u32 start;
@@ -381,7 +378,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
}
}
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
if (i == obj->nr_tlb_entries)
dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
@@ -395,7 +392,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
{
struct iotlb_lock l;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
l.base = 0;
l.vict = 0;
@@ -403,7 +400,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
iommu_write_reg(obj, 1, MMU_GFLUSH);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
}
#if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
@@ -413,11 +410,11 @@ ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
if (!obj || !buf)
return -EINVAL;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
bytes = arch_iommu->dump_ctx(obj, buf, bytes);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return bytes;
}
@@ -431,7 +428,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
struct cr_regs tmp;
struct cr_regs *p = crs;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
iotlb_lock_get(obj, &saved);
for_each_iotlb_cr(obj, num, i, tmp) {
@@ -441,7 +438,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
}
iotlb_lock_set(obj, &saved);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return p - crs;
}
@@ -805,9 +802,7 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
if (!obj->refcount)
return IRQ_NONE;
- clk_enable(obj->clk);
errs = iommu_report_fault(obj, &da);
- clk_disable(obj->clk);
if (errs == 0)
return IRQ_HANDLED;
@@ -933,10 +928,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
if (!obj)
return -ENOMEM;
- obj->clk = clk_get(&pdev->dev, pdata->clk_name);
- if (IS_ERR(obj->clk))
- goto err_clk;
-
obj->nr_tlb_entries = pdata->nr_tlb_entries;
obj->name = pdata->name;
obj->dev = &pdev->dev;
@@ -979,6 +970,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
goto err_irq;
platform_set_drvdata(pdev, obj);
+ pm_runtime_irq_safe(obj->dev);
+ pm_runtime_enable(obj->dev);
+
dev_info(&pdev->dev, "%s registered\n", obj->name);
return 0;
@@ -987,8 +981,6 @@ err_irq:
err_ioremap:
release_mem_region(res->start, resource_size(res));
err_mem:
- clk_put(obj->clk);
-err_clk:
kfree(obj);
return err;
}
@@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
release_mem_region(res->start, resource_size(res));
iounmap(obj->regbase);
- clk_put(obj->clk);
+ pm_runtime_disable(obj->dev);
+
dev_info(&pdev->dev, "%s removed\n", obj->name);
kfree(obj);
return 0;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350003977-32744-1-git-send-email-omar.luna@linaro.org>
Use runtime PM functionality interfaced with hwmod enable/idle
functions, to replace direct clock operations and sysconfig
handling.
Dues to reset sequence, pm_runtime_put_sync must be used, to avoid
possible operations with the module under reset.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/mach-omap2/iommu2.c | 17 -----------
arch/arm/mach-omap2/omap-iommu.c | 1 -
arch/arm/plat-omap/include/plat/iommu.h | 2 --
arch/arm/plat-omap/include/plat/iommu2.h | 2 --
drivers/iommu/omap-iommu.c | 45 +++++++++++++-----------------
5 files changed, 19 insertions(+), 48 deletions(-)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 35cab47..3e47786 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -25,15 +25,6 @@
*/
#define IOMMU_ARCH_VERSION 0x00000011
-/* SYSCONF */
-#define MMU_SYS_IDLE_SHIFT 3
-#define MMU_SYS_IDLE_FORCE (0 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_NONE (1 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT)
-
-#define MMU_SYS_AUTOIDLE 1
-
/* IRQSTATUS & IRQENABLE */
#define MMU_IRQ_MULTIHITFAULT (1 << 4)
#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
@@ -96,11 +87,6 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
(l >> 4) & 0xf, l & 0xf);
- l = iommu_read_reg(obj, MMU_SYSCONFIG);
- l &= ~MMU_SYS_IDLE_MASK;
- l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
- iommu_write_reg(obj, l, MMU_SYSCONFIG);
-
iommu_write_reg(obj, pa, MMU_TTB);
__iommu_set_twl(obj, true);
@@ -114,7 +100,6 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
l &= ~MMU_CNTL_MASK;
iommu_write_reg(obj, l, MMU_CNTL);
- iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG);
dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
}
@@ -243,8 +228,6 @@ omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
char *p = buf;
pr_reg(REVISION);
- pr_reg(SYSCONFIG);
- pr_reg(SYSSTATUS);
pr_reg(IRQSTATUS);
pr_reg(IRQENABLE);
pr_reg(WALKING_ST);
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index e400845..82a422a 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -34,7 +34,6 @@ static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
return -ENOMEM;
pdata->name = oh->name;
- pdata->clk_name = oh->main_clk;
pdata->nr_tlb_entries = a->nr_tlb_entries;
pdata->da_start = a->da_start;
pdata->da_end = a->da_end;
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 0fa913d..902d193 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -30,7 +30,6 @@ struct iotlb_entry {
struct omap_iommu {
const char *name;
struct module *owner;
- struct clk *clk;
void __iomem *regbase;
struct device *dev;
void *isr_priv;
@@ -120,7 +119,6 @@ struct omap_mmu_dev_attr {
struct iommu_platform_data {
const char *name;
- const char *clk_name;
const char *reset_name;
int nr_tlb_entries;
u32 da_start;
diff --git a/arch/arm/plat-omap/include/plat/iommu2.h b/arch/arm/plat-omap/include/plat/iommu2.h
index d4116b5..1579694 100644
--- a/arch/arm/plat-omap/include/plat/iommu2.h
+++ b/arch/arm/plat-omap/include/plat/iommu2.h
@@ -19,8 +19,6 @@
* MMU Register offsets
*/
#define MMU_REVISION 0x00
-#define MMU_SYSCONFIG 0x10
-#define MMU_SYSSTATUS 0x14
#define MMU_IRQSTATUS 0x18
#define MMU_IRQENABLE 0x1c
#define MMU_WALKING_ST 0x40
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index c1caee4..37644c4 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -16,11 +16,11 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
-#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/iommu.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
#include <asm/cacheflush.h>
@@ -142,11 +142,10 @@ static int iommu_enable(struct omap_iommu *obj)
}
}
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
err = arch_iommu->enable(obj);
- clk_disable(obj->clk);
return err;
}
@@ -158,11 +157,9 @@ static void iommu_disable(struct omap_iommu *obj)
if (!obj || !pdata)
return;
- clk_enable(obj->clk);
-
arch_iommu->disable(obj);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
if (pdata->assert_reset)
pdata->assert_reset(pdev, pdata->reset_name);
@@ -288,7 +285,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
if (!obj || !obj->nr_tlb_entries || !e)
return -EINVAL;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
iotlb_lock_get(obj, &l);
if (l.base == obj->nr_tlb_entries) {
@@ -318,7 +315,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
cr = iotlb_alloc_cr(obj, e);
if (IS_ERR(cr)) {
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return PTR_ERR(cr);
}
@@ -332,7 +329,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
l.vict = l.base;
iotlb_lock_set(obj, &l);
out:
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return err;
}
@@ -362,7 +359,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
int i;
struct cr_regs cr;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
u32 start;
@@ -381,7 +378,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
}
}
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
if (i == obj->nr_tlb_entries)
dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
@@ -395,7 +392,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
{
struct iotlb_lock l;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
l.base = 0;
l.vict = 0;
@@ -403,7 +400,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
iommu_write_reg(obj, 1, MMU_GFLUSH);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
}
#if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
@@ -413,11 +410,11 @@ ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
if (!obj || !buf)
return -EINVAL;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
bytes = arch_iommu->dump_ctx(obj, buf, bytes);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return bytes;
}
@@ -431,7 +428,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
struct cr_regs tmp;
struct cr_regs *p = crs;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
iotlb_lock_get(obj, &saved);
for_each_iotlb_cr(obj, num, i, tmp) {
@@ -441,7 +438,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
}
iotlb_lock_set(obj, &saved);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return p - crs;
}
@@ -805,9 +802,7 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
if (!obj->refcount)
return IRQ_NONE;
- clk_enable(obj->clk);
errs = iommu_report_fault(obj, &da);
- clk_disable(obj->clk);
if (errs == 0)
return IRQ_HANDLED;
@@ -933,10 +928,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
if (!obj)
return -ENOMEM;
- obj->clk = clk_get(&pdev->dev, pdata->clk_name);
- if (IS_ERR(obj->clk))
- goto err_clk;
-
obj->nr_tlb_entries = pdata->nr_tlb_entries;
obj->name = pdata->name;
obj->dev = &pdev->dev;
@@ -979,6 +970,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
goto err_irq;
platform_set_drvdata(pdev, obj);
+ pm_runtime_irq_safe(obj->dev);
+ pm_runtime_enable(obj->dev);
+
dev_info(&pdev->dev, "%s registered\n", obj->name);
return 0;
@@ -987,8 +981,6 @@ err_irq:
err_ioremap:
release_mem_region(res->start, resource_size(res));
err_mem:
- clk_put(obj->clk);
-err_clk:
kfree(obj);
return err;
}
@@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
release_mem_region(res->start, resource_size(res));
iounmap(obj->regbase);
- clk_put(obj->clk);
+ pm_runtime_disable(obj->dev);
+
dev_info(&pdev->dev, "%s removed\n", obj->name);
kfree(obj);
return 0;
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/6] ARM: OMAP3/4: iommu: migrate to hwmod framework
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350003977-32744-1-git-send-email-omar.luna@linaro.org>
Use hwmod data and device attributes to build and register an
omap device for iommu driver.
- Update the naming convention in isp module.
- Remove unneeded check for number of resources, as this is now
handled by omap_device and prevents driver from loading.
- Now unused, remove platform device and resource data, handling
of sysconfig register for softreset purposes, use default
latency structure.
- Use hwmod API for reset handling.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/mach-omap2/devices.c | 2 +-
arch/arm/mach-omap2/iommu2.c | 19 ----
arch/arm/mach-omap2/omap-iommu.c | 165 +++++++------------------------
arch/arm/plat-omap/include/plat/iommu.h | 8 +-
drivers/iommu/omap-iommu.c | 23 ++++-
5 files changed, 64 insertions(+), 153 deletions(-)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index c8c2117..e084b94 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -213,7 +213,7 @@ static struct platform_device omap3isp_device = {
};
static struct omap_iommu_arch_data omap3_isp_iommu = {
- .name = "isp",
+ .name = "mmu_isp",
};
int omap3_init_camera(struct isp_platform_data *pdata)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index eefc379..35cab47 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -32,12 +32,8 @@
#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT)
#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_SOFTRESET (1 << 1)
#define MMU_SYS_AUTOIDLE 1
-/* SYSSTATUS */
-#define MMU_SYS_RESETDONE 1
-
/* IRQSTATUS & IRQENABLE */
#define MMU_IRQ_MULTIHITFAULT (1 << 4)
#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
@@ -88,7 +84,6 @@ static void __iommu_set_twl(struct omap_iommu *obj, bool on)
static int omap2_iommu_enable(struct omap_iommu *obj)
{
u32 l, pa;
- unsigned long timeout;
if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
return -EINVAL;
@@ -97,20 +92,6 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
if (!IS_ALIGNED(pa, SZ_16K))
return -EINVAL;
- iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG);
-
- timeout = jiffies + msecs_to_jiffies(20);
- do {
- l = iommu_read_reg(obj, MMU_SYSSTATUS);
- if (l & MMU_SYS_RESETDONE)
- break;
- } while (!time_after(jiffies, timeout));
-
- if (!(l & MMU_SYS_RESETDONE)) {
- dev_err(obj->dev, "can't take mmu out of reset\n");
- return -ENODEV;
- }
-
l = iommu_read_reg(obj, MMU_REVISION);
dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
(l >> 4) & 0xf, l & 0xf);
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index df298d4..e400845 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -12,153 +12,64 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
#include <plat/iommu.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
#include "soc.h"
#include "common.h"
-struct iommu_device {
- resource_size_t base;
- int irq;
- struct iommu_platform_data pdata;
- struct resource res[2];
-};
-static struct iommu_device *devices;
-static int num_iommu_devices;
-
-#ifdef CONFIG_ARCH_OMAP3
-static struct iommu_device omap3_devices[] = {
- {
- .base = 0x480bd400,
- .irq = 24 + OMAP_INTC_START,
- .pdata = {
- .name = "isp",
- .nr_tlb_entries = 8,
- .clk_name = "cam_ick",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
- },
-#if defined(CONFIG_OMAP_IOMMU_IVA2)
- {
- .base = 0x5d000000,
- .irq = 28 + OMAP_INTC_START,
- .pdata = {
- .name = "iva2",
- .nr_tlb_entries = 32,
- .clk_name = "iva2_ck",
- .da_start = 0x11000000,
- .da_end = 0xFFFFF000,
- },
- },
-#endif
-};
-#define NR_OMAP3_IOMMU_DEVICES ARRAY_SIZE(omap3_devices)
-static struct platform_device *omap3_iommu_pdev[NR_OMAP3_IOMMU_DEVICES];
-#else
-#define omap3_devices NULL
-#define NR_OMAP3_IOMMU_DEVICES 0
-#define omap3_iommu_pdev NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP4
-static struct iommu_device omap4_devices[] = {
- {
- .base = OMAP4_MMU1_BASE,
- .irq = 100 + OMAP44XX_IRQ_GIC_START,
- .pdata = {
- .name = "ducati",
- .nr_tlb_entries = 32,
- .clk_name = "ipu_fck",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
- },
- {
- .base = OMAP4_MMU2_BASE,
- .irq = 28 + OMAP44XX_IRQ_GIC_START,
- .pdata = {
- .name = "tesla",
- .nr_tlb_entries = 32,
- .clk_name = "dsp_fck",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
- },
-};
-#define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices)
-static struct platform_device *omap4_iommu_pdev[NR_OMAP4_IOMMU_DEVICES];
-#else
-#define omap4_devices NULL
-#define NR_OMAP4_IOMMU_DEVICES 0
-#define omap4_iommu_pdev NULL
-#endif
-
-static struct platform_device **omap_iommu_pdev;
-
-static int __init omap_iommu_init(void)
+static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
{
- int i, err;
- struct resource res[] = {
- { .flags = IORESOURCE_MEM },
- { .flags = IORESOURCE_IRQ },
- };
+ struct platform_device *pdev;
+ struct iommu_platform_data *pdata;
+ struct omap_mmu_dev_attr *a = (struct omap_mmu_dev_attr *)oh->dev_attr;
+ static int i;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdata->name = oh->name;
+ pdata->clk_name = oh->main_clk;
+ pdata->nr_tlb_entries = a->nr_tlb_entries;
+ pdata->da_start = a->da_start;
+ pdata->da_end = a->da_end;
+
+ if (oh->rst_lines_cnt == 1) {
+ pdata->reset_name = oh->rst_lines->name;
+ pdata->assert_reset = omap_device_assert_hardreset;
+ pdata->deassert_reset = omap_device_deassert_hardreset;
+ }
- if (cpu_is_omap34xx()) {
- devices = omap3_devices;
- omap_iommu_pdev = omap3_iommu_pdev;
- num_iommu_devices = NR_OMAP3_IOMMU_DEVICES;
- } else if (cpu_is_omap44xx()) {
- devices = omap4_devices;
- omap_iommu_pdev = omap4_iommu_pdev;
- num_iommu_devices = NR_OMAP4_IOMMU_DEVICES;
- } else
- return -ENODEV;
+ pdev = omap_device_build("omap-iommu", i, oh, pdata, sizeof(*pdata),
+ NULL, 0, 0);
- for (i = 0; i < num_iommu_devices; i++) {
- struct platform_device *pdev;
- const struct iommu_device *d = &devices[i];
+ kfree(pdata);
- pdev = platform_device_alloc("omap-iommu", i);
- if (!pdev) {
- err = -ENOMEM;
- goto err_out;
- }
+ if (IS_ERR(pdev)) {
+ pr_err("%s: device build err: %ld\n", __func__, PTR_ERR(pdev));
+ return PTR_ERR(pdev);
+ }
- res[0].start = d->base;
- res[0].end = d->base + MMU_REG_SIZE - 1;
- res[1].start = res[1].end = d->irq;
+ i++;
- err = platform_device_add_resources(pdev, res,
- ARRAY_SIZE(res));
- if (err)
- goto err_out;
- err = platform_device_add_data(pdev, &d->pdata,
- sizeof(d->pdata));
- if (err)
- goto err_out;
- err = platform_device_add(pdev);
- if (err)
- goto err_out;
- omap_iommu_pdev[i] = pdev;
- }
return 0;
+}
-err_out:
- while (i--)
- platform_device_put(omap_iommu_pdev[i]);
- return err;
+static int __init omap_iommu_init(void)
+{
+ return omap_hwmod_for_each_by_class("mmu", omap_iommu_dev_init, NULL);
}
/* must be ready before omap3isp is probed */
subsys_initcall(omap_iommu_init);
static void __exit omap_iommu_exit(void)
{
- int i;
-
- for (i = 0; i < num_iommu_devices; i++)
- platform_device_unregister(omap_iommu_pdev[i]);
+ /* Do nothing */
}
module_exit(omap_iommu_exit);
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 68b5f03..0fa913d 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -13,6 +13,8 @@
#ifndef __MACH_IOMMU_H
#define __MACH_IOMMU_H
+#include <linux/platform_device.h>
+
struct iotlb_entry {
u32 da;
u32 pa;
@@ -119,9 +121,13 @@ struct omap_mmu_dev_attr {
struct iommu_platform_data {
const char *name;
const char *clk_name;
- const int nr_tlb_entries;
+ const char *reset_name;
+ int nr_tlb_entries;
u32 da_start;
u32 da_end;
+
+ int (*assert_reset)(struct platform_device *pdev, const char *name);
+ int (*deassert_reset)(struct platform_device *pdev, const char *name);
};
/**
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index d0b1234..c1caee4 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -125,13 +125,23 @@ EXPORT_SYMBOL_GPL(omap_iommu_arch_version);
static int iommu_enable(struct omap_iommu *obj)
{
int err;
+ struct platform_device *pdev = to_platform_device(obj->dev);
+ struct iommu_platform_data *pdata = pdev->dev.platform_data;
- if (!obj)
+ if (!obj || !pdata)
return -EINVAL;
if (!arch_iommu)
return -ENODEV;
+ if (pdata->deassert_reset) {
+ err = pdata->deassert_reset(pdev, pdata->reset_name);
+ if (err) {
+ dev_err(obj->dev, "deassert_reset failed: %d\n", err);
+ return err;
+ }
+ }
+
clk_enable(obj->clk);
err = arch_iommu->enable(obj);
@@ -142,7 +152,10 @@ static int iommu_enable(struct omap_iommu *obj)
static void iommu_disable(struct omap_iommu *obj)
{
- if (!obj)
+ struct platform_device *pdev = to_platform_device(obj->dev);
+ struct iommu_platform_data *pdata = pdev->dev.platform_data;
+
+ if (!obj || !pdata)
return;
clk_enable(obj->clk);
@@ -150,6 +163,9 @@ static void iommu_disable(struct omap_iommu *obj)
arch_iommu->disable(obj);
clk_disable(obj->clk);
+
+ if (pdata->assert_reset)
+ pdata->assert_reset(pdev, pdata->reset_name);
}
/*
@@ -913,9 +929,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
struct resource *res;
struct iommu_platform_data *pdata = pdev->dev.platform_data;
- if (pdev->num_resources != 2)
- return -EINVAL;
-
obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
if (!obj)
return -ENOMEM;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 1/6] ARM: OMAP3/4: iommu: migrate to hwmod framework
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350003977-32744-1-git-send-email-omar.luna@linaro.org>
Use hwmod data and device attributes to build and register an
omap device for iommu driver.
- Update the naming convention in isp module.
- Remove unneeded check for number of resources, as this is now
handled by omap_device and prevents driver from loading.
- Now unused, remove platform device and resource data, handling
of sysconfig register for softreset purposes, use default
latency structure.
- Use hwmod API for reset handling.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/mach-omap2/devices.c | 2 +-
arch/arm/mach-omap2/iommu2.c | 19 ----
arch/arm/mach-omap2/omap-iommu.c | 165 +++++++------------------------
arch/arm/plat-omap/include/plat/iommu.h | 8 +-
drivers/iommu/omap-iommu.c | 23 ++++-
5 files changed, 64 insertions(+), 153 deletions(-)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index c8c2117..e084b94 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -213,7 +213,7 @@ static struct platform_device omap3isp_device = {
};
static struct omap_iommu_arch_data omap3_isp_iommu = {
- .name = "isp",
+ .name = "mmu_isp",
};
int omap3_init_camera(struct isp_platform_data *pdata)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index eefc379..35cab47 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -32,12 +32,8 @@
#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT)
#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_SOFTRESET (1 << 1)
#define MMU_SYS_AUTOIDLE 1
-/* SYSSTATUS */
-#define MMU_SYS_RESETDONE 1
-
/* IRQSTATUS & IRQENABLE */
#define MMU_IRQ_MULTIHITFAULT (1 << 4)
#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
@@ -88,7 +84,6 @@ static void __iommu_set_twl(struct omap_iommu *obj, bool on)
static int omap2_iommu_enable(struct omap_iommu *obj)
{
u32 l, pa;
- unsigned long timeout;
if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
return -EINVAL;
@@ -97,20 +92,6 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
if (!IS_ALIGNED(pa, SZ_16K))
return -EINVAL;
- iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG);
-
- timeout = jiffies + msecs_to_jiffies(20);
- do {
- l = iommu_read_reg(obj, MMU_SYSSTATUS);
- if (l & MMU_SYS_RESETDONE)
- break;
- } while (!time_after(jiffies, timeout));
-
- if (!(l & MMU_SYS_RESETDONE)) {
- dev_err(obj->dev, "can't take mmu out of reset\n");
- return -ENODEV;
- }
-
l = iommu_read_reg(obj, MMU_REVISION);
dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
(l >> 4) & 0xf, l & 0xf);
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index df298d4..e400845 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -12,153 +12,64 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
#include <plat/iommu.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
#include "soc.h"
#include "common.h"
-struct iommu_device {
- resource_size_t base;
- int irq;
- struct iommu_platform_data pdata;
- struct resource res[2];
-};
-static struct iommu_device *devices;
-static int num_iommu_devices;
-
-#ifdef CONFIG_ARCH_OMAP3
-static struct iommu_device omap3_devices[] = {
- {
- .base = 0x480bd400,
- .irq = 24 + OMAP_INTC_START,
- .pdata = {
- .name = "isp",
- .nr_tlb_entries = 8,
- .clk_name = "cam_ick",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
- },
-#if defined(CONFIG_OMAP_IOMMU_IVA2)
- {
- .base = 0x5d000000,
- .irq = 28 + OMAP_INTC_START,
- .pdata = {
- .name = "iva2",
- .nr_tlb_entries = 32,
- .clk_name = "iva2_ck",
- .da_start = 0x11000000,
- .da_end = 0xFFFFF000,
- },
- },
-#endif
-};
-#define NR_OMAP3_IOMMU_DEVICES ARRAY_SIZE(omap3_devices)
-static struct platform_device *omap3_iommu_pdev[NR_OMAP3_IOMMU_DEVICES];
-#else
-#define omap3_devices NULL
-#define NR_OMAP3_IOMMU_DEVICES 0
-#define omap3_iommu_pdev NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP4
-static struct iommu_device omap4_devices[] = {
- {
- .base = OMAP4_MMU1_BASE,
- .irq = 100 + OMAP44XX_IRQ_GIC_START,
- .pdata = {
- .name = "ducati",
- .nr_tlb_entries = 32,
- .clk_name = "ipu_fck",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
- },
- {
- .base = OMAP4_MMU2_BASE,
- .irq = 28 + OMAP44XX_IRQ_GIC_START,
- .pdata = {
- .name = "tesla",
- .nr_tlb_entries = 32,
- .clk_name = "dsp_fck",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
- },
-};
-#define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices)
-static struct platform_device *omap4_iommu_pdev[NR_OMAP4_IOMMU_DEVICES];
-#else
-#define omap4_devices NULL
-#define NR_OMAP4_IOMMU_DEVICES 0
-#define omap4_iommu_pdev NULL
-#endif
-
-static struct platform_device **omap_iommu_pdev;
-
-static int __init omap_iommu_init(void)
+static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
{
- int i, err;
- struct resource res[] = {
- { .flags = IORESOURCE_MEM },
- { .flags = IORESOURCE_IRQ },
- };
+ struct platform_device *pdev;
+ struct iommu_platform_data *pdata;
+ struct omap_mmu_dev_attr *a = (struct omap_mmu_dev_attr *)oh->dev_attr;
+ static int i;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdata->name = oh->name;
+ pdata->clk_name = oh->main_clk;
+ pdata->nr_tlb_entries = a->nr_tlb_entries;
+ pdata->da_start = a->da_start;
+ pdata->da_end = a->da_end;
+
+ if (oh->rst_lines_cnt == 1) {
+ pdata->reset_name = oh->rst_lines->name;
+ pdata->assert_reset = omap_device_assert_hardreset;
+ pdata->deassert_reset = omap_device_deassert_hardreset;
+ }
- if (cpu_is_omap34xx()) {
- devices = omap3_devices;
- omap_iommu_pdev = omap3_iommu_pdev;
- num_iommu_devices = NR_OMAP3_IOMMU_DEVICES;
- } else if (cpu_is_omap44xx()) {
- devices = omap4_devices;
- omap_iommu_pdev = omap4_iommu_pdev;
- num_iommu_devices = NR_OMAP4_IOMMU_DEVICES;
- } else
- return -ENODEV;
+ pdev = omap_device_build("omap-iommu", i, oh, pdata, sizeof(*pdata),
+ NULL, 0, 0);
- for (i = 0; i < num_iommu_devices; i++) {
- struct platform_device *pdev;
- const struct iommu_device *d = &devices[i];
+ kfree(pdata);
- pdev = platform_device_alloc("omap-iommu", i);
- if (!pdev) {
- err = -ENOMEM;
- goto err_out;
- }
+ if (IS_ERR(pdev)) {
+ pr_err("%s: device build err: %ld\n", __func__, PTR_ERR(pdev));
+ return PTR_ERR(pdev);
+ }
- res[0].start = d->base;
- res[0].end = d->base + MMU_REG_SIZE - 1;
- res[1].start = res[1].end = d->irq;
+ i++;
- err = platform_device_add_resources(pdev, res,
- ARRAY_SIZE(res));
- if (err)
- goto err_out;
- err = platform_device_add_data(pdev, &d->pdata,
- sizeof(d->pdata));
- if (err)
- goto err_out;
- err = platform_device_add(pdev);
- if (err)
- goto err_out;
- omap_iommu_pdev[i] = pdev;
- }
return 0;
+}
-err_out:
- while (i--)
- platform_device_put(omap_iommu_pdev[i]);
- return err;
+static int __init omap_iommu_init(void)
+{
+ return omap_hwmod_for_each_by_class("mmu", omap_iommu_dev_init, NULL);
}
/* must be ready before omap3isp is probed */
subsys_initcall(omap_iommu_init);
static void __exit omap_iommu_exit(void)
{
- int i;
-
- for (i = 0; i < num_iommu_devices; i++)
- platform_device_unregister(omap_iommu_pdev[i]);
+ /* Do nothing */
}
module_exit(omap_iommu_exit);
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 68b5f03..0fa913d 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -13,6 +13,8 @@
#ifndef __MACH_IOMMU_H
#define __MACH_IOMMU_H
+#include <linux/platform_device.h>
+
struct iotlb_entry {
u32 da;
u32 pa;
@@ -119,9 +121,13 @@ struct omap_mmu_dev_attr {
struct iommu_platform_data {
const char *name;
const char *clk_name;
- const int nr_tlb_entries;
+ const char *reset_name;
+ int nr_tlb_entries;
u32 da_start;
u32 da_end;
+
+ int (*assert_reset)(struct platform_device *pdev, const char *name);
+ int (*deassert_reset)(struct platform_device *pdev, const char *name);
};
/**
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index d0b1234..c1caee4 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -125,13 +125,23 @@ EXPORT_SYMBOL_GPL(omap_iommu_arch_version);
static int iommu_enable(struct omap_iommu *obj)
{
int err;
+ struct platform_device *pdev = to_platform_device(obj->dev);
+ struct iommu_platform_data *pdata = pdev->dev.platform_data;
- if (!obj)
+ if (!obj || !pdata)
return -EINVAL;
if (!arch_iommu)
return -ENODEV;
+ if (pdata->deassert_reset) {
+ err = pdata->deassert_reset(pdev, pdata->reset_name);
+ if (err) {
+ dev_err(obj->dev, "deassert_reset failed: %d\n", err);
+ return err;
+ }
+ }
+
clk_enable(obj->clk);
err = arch_iommu->enable(obj);
@@ -142,7 +152,10 @@ static int iommu_enable(struct omap_iommu *obj)
static void iommu_disable(struct omap_iommu *obj)
{
- if (!obj)
+ struct platform_device *pdev = to_platform_device(obj->dev);
+ struct iommu_platform_data *pdata = pdev->dev.platform_data;
+
+ if (!obj || !pdata)
return;
clk_enable(obj->clk);
@@ -150,6 +163,9 @@ static void iommu_disable(struct omap_iommu *obj)
arch_iommu->disable(obj);
clk_disable(obj->clk);
+
+ if (pdata->assert_reset)
+ pdata->assert_reset(pdev, pdata->reset_name);
}
/*
@@ -913,9 +929,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
struct resource *res;
struct iommu_platform_data *pdata = pdev->dev.platform_data;
- if (pdev->num_resources != 2)
- return -EINVAL;
-
obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
if (!obj)
return -ENOMEM;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
These patches are needed for remoteproc to work on OMAP4.
Introduced iommu hwmod support for OMAP3 (iva, isp) and
OMAP4 (ipu, dsp), along with the corresponding runtime PM
and routines to deassert reset lines, enable/disable clocks
and configure sysc registers.
Although IOMMU hwmod patches were already submitted in the past,
this series adds few more changes, like:
- New reset handling.
- Save and restore context code rework.
- Device tree bindings for OMAP3 and OMAP4.
For this series I just dropped the patches already included in
mainline.
Previous work can be found at:
[v2]
http://www.mail-archive.com/linux-omap at vger.kernel.org/msg75701.html
[v1]
http://www.mail-archive.com/linux-omap at vger.kernel.org/msg70447.html
[old iteration without reset, save/restore and device tree]
http://www.mail-archive.com/linux-omap at vger.kernel.org/msg60133.html
Omar Ramirez Luna (6):
ARM: OMAP3/4: iommu: migrate to hwmod framework
ARM: OMAP3/4: iommu: adapt to runtime pm
ARM: OMAP: iommu: pm runtime save and restore context
ARM: OMAP: iommu: optimize save and restore routines
ARM: OMAP: iommu: add device tree support
arm/dts: OMAP3/4: Add iommu nodes
.../devicetree/bindings/arm/omap/iommu.txt | 10 ++
arch/arm/boot/dts/omap3.dtsi | 12 +-
arch/arm/boot/dts/omap4.dtsi | 17 +-
arch/arm/mach-omap2/devices.c | 2 +-
arch/arm/mach-omap2/iommu2.c | 74 ++------
arch/arm/mach-omap2/omap-iommu.c | 176 +++++---------------
arch/arm/plat-omap/include/plat/iommu.h | 20 ++-
arch/arm/plat-omap/include/plat/iommu2.h | 4 -
drivers/iommu/omap-iommu.c | 163 ++++++++++++++----
9 files changed, 245 insertions(+), 233 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/omap/iommu.txt
--
1.7.9.5
^ permalink raw reply
* [PATCH 2/2] ARM: unwind: enable dumping stacks for SMP && ARM_UNWIND
From: Laura Abbott @ 2012-10-12 0:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1346021216-21979-3-git-send-email-ccross@android.com>
Hi,
On 8/26/2012 3:46 PM, Colin Cross wrote:
> Unwinding with CONFIG_ARM_UNWIND is much more complicated than
> unwinding with CONFIG_FRAME_POINTER, but there are only a few points
> that require validation in order to avoid faults or infinite loops.
> Avoiding faults is easy by adding checks to verify that all accesses
> relative to the frame's stack pointer remain inside the stack.
>
> When CONFIG_FRAME_POINTER is not set it is possible for two frames to
> have the same SP, so there is no way to avoid repeated calls to
> unwind_frame continuing forever.
>
> Signed-off-by: Colin Cross <ccross@android.com>
> ---
This is a feature we've wanted for a long time. I ran some test with
repeated catting of stacks with processes dying and the results looked good.
You can add a Tested-by: Laura Abbott <lauraa@codeaurora.org>
Laura
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* [PATCH 1/2] ARM: nomadik: switch over to using the FSMC driver
From: Mike Turquette @ 2012-10-11 23:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdYMz05DwtLtHkggvo8VFOtvPLpovwq6fLceeiFK0Wci0Q@mail.gmail.com>
Quoting Linus Walleij (2012-10-05 05:52:06)
> On Thu, Oct 4, 2012 at 9:28 AM, Linus Walleij <linus.walleij@linaro.org> wrote:
>
> > The Nomadik NAND driver is really just a subset of the existing
> > FSMC driver, so let's switch over to using that driver instead,
> > since it handles more variants of this chip. The callbacks for
> > setting up the chip is doing stuff now handled by the FSMC
> > driver.
> >
> > Cc: Alessandro Rubini <rubini@unipv.it>
> > Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> > ---
> > I'm requesting Mike Turquette's ACK on this patch so I can merge
> > it through ARM SoC.
>
> Still requesting Mike's ACK, but not for merging through ARM SoC
> but through MTD.
>
Sorry for the late response but I just returned from vacation. Might be
too late but:
Acked-by: Mike Turquette <mturquette@linaro.org>
Thanks,
Mike
> If you apply Jean-Christophe's patch first (please do that) I will
> send a v2 of this patch set to be applied onto MTD as well
> (should be OK).
>
> Yours,
> Linus Walleij
^ permalink raw reply
* new branch for linux-next [Was: [PATCH v6 0/3] Updated Cortex-M3 series]
From: Stephen Rothwell @ 2012-10-11 22:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121008154659.GY4625@n2100.arm.linux.org.uk>
Hi Uwe,
On Mon, 8 Oct 2012 16:47:00 +0100 Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
>
> On Mon, Oct 08, 2012 at 05:43:25PM +0200, Uwe Kleine-K?nig wrote:
> >
> > I already tried several times to get feedback from Russell King (as you
> > probably know he's the ARM maintainer and busy most of the time) for my
> > series to support Cortex-M3 machines. As I think the outcome will
> > probably (at least) be that it should be included in next for some time
> > first (as for example Arnd Bergmann already suggested), can you please
> > add
> >
> > git://git.pengutronix.de/git/ukl/linux-2.6.git for-next
> >
> > to your tree? I'd suggest adding it after arm and arm-soc.
> > I intend to use this branch later for efm32 support (which depends on
> > the Cortex-M3 stuff).
> >
> > Currently the branch is still empty, but I intend to fill it with what I
> > consider to be applyable after I did some more testing. (Mainly to
> > assert it still does what it did when I developed it on an older base.)
> >
> > @Russell: I hope this is OK for you. If not, I'm sure you'll protest.
>
> Well, I think the patches are mostly fine but I do think more eyes are
> needed on them first. I heard today that some people will be looking
> at your Cortex M3 stuff, and hopefully that should move things forward.
I generally don't add new trees to linux-next during the merge window,
so, if you don't hear from me that I have added it, please remind me
about this after Linus releases v3.7-rc1.
--
Cheers,
Stephen Rothwell sfr at canb.auug.org.au
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121012/290f4d2b/attachment.sig>
^ permalink raw reply
* [GIT PULL] Versatile Express clk
From: Mike Turquette @ 2012-10-11 22:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1348501568.27071.5.camel@hornet>
Quoting Pawel Moll (2012-09-24 08:46:08)
> Hi Mike,
>
> Would you be so kind and pull the VE clocking stuff? They are rebased on
> top of Linus' Realview patch.
>
Hi Pawel,
I've taken these into my new clk-next towards 3.8. That branch is not
yet pushed out publicly but will be after -rc1 is released.
Regards,
Mike
> Thanks!
>
> Pawel
>
>
> The following changes since commit b9f8a0f8e255919bdcfb96a8d50d1523233a458a:
>
> clk: convert ARM RealView to common clk (2012-09-24 16:28:29 +0100)
>
> are available in the git repository at:
>
> git://git.linaro.org/people/pawelmoll/linux.git clk-v3.6-rc7
>
> for you to fetch changes up to b262f1ed394218f9327b72e7d1d17a5e62074be0:
>
> clk: Common clocks implementation for Versatile Express (2012-09-24 16:28:30 +0100)
>
> ----------------------------------------------------------------
> Pawel Moll (2):
> clk: Versatile Express clock generators ("osc") driver
> clk: Common clocks implementation for Versatile Express
>
> arch/arm/include/asm/hardware/sp810.h | 2 +
> drivers/clk/Kconfig | 8 +-
> drivers/clk/versatile/Makefile | 2 +
> drivers/clk/versatile/clk-vexpress-osc.c | 150 ++++++++++++++++++++++++++++++
> drivers/clk/versatile/clk-vexpress.c | 142 ++++++++++++++++++++++++++++
> 5 files changed, 301 insertions(+), 3 deletions(-)
> create mode 100644 drivers/clk/versatile/clk-vexpress-osc.c
> create mode 100644 drivers/clk/versatile/clk-vexpress.c
^ 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