Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] timer: vt8500: Convert vt8500 to use CLKSRC_OF
From: Olof Johansson @ 2013-01-15 19:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358232649-19964-1-git-send-email-linux@prisktech.co.nz>

On Tue, Jan 15, 2013 at 07:50:49PM +1300, Tony Prisk wrote:
> This patch converts arch-vt8500 to make use of CLKSRC_OF. Doing so
> removes the need for include/linux/vt8500_timer.h as vt8500_timer_init
> no longer needs to be visible outside vt8500_timer.c
> 
> Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
> ---
> Hi Olof,
> 
> Here is the fix as requested by Stephen Warren, based on vt8500/timer.

Applied, thanks.


-Olof

^ permalink raw reply

* [PATCH v2 3/3 RFT] ARM: tegra: dts: seaboard: enable keyboard
From: Stephen Warren @ 2013-01-15 18:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358234689-18126-1-git-send-email-ldewangan@nvidia.com>

On 01/15/2013 12:24 AM, Laxman Dewangan wrote:
> Enable tegra based keyboard controller and populate the key matrix for
> seaboard. The key matrix was originally on driver code which is removed
> to have clean driver. The key mapping is now passed through dts file.

Applied to Tegra's for-3.9/dt branch.

^ permalink raw reply

* [PATCH 2/3] ARM: tegra: config: enable KEYBOARD_TEGRA
From: Stephen Warren @ 2013-01-15 18:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1357911185-11048-2-git-send-email-ldewangan@nvidia.com>

On 01/11/2013 06:33 AM, Laxman Dewangan wrote:

Squashed into Tegra's for-3.9/defconfig branch.

^ permalink raw reply

* [PATCH 1/3] ARM: DT: tegra: add DT entry for KBC controller
From: Stephen Warren @ 2013-01-15 18:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1357911185-11048-1-git-send-email-ldewangan@nvidia.com>

On 01/11/2013 06:33 AM, Laxman Dewangan wrote:
> NVIDIA's Tegra SoCs have the matrix keyboard controller which
> supports 16x8 type of matrix. The number of rows and columns
> are configurable.
> 
> Add DT entry for KBC controller.

Applied to Tegra's for-3.9/dt branch.

I added the required clocks property for this patch to work with
Prashant's common clock framework port, although it's commented out so
far, until the CCF rework is actually applied.

^ permalink raw reply

* [PATCH v8 5/5] ARM: OMAP: gpmc: add DT bindings for GPMC timings and NAND
From: Tony Lindgren @ 2013-01-15 18:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CALF0-+WpCc=291-thQz2=U_kBFztaq50j+U=Hm8C9ho3UZBejw@mail.gmail.com>

* Ezequiel Garcia <elezegarcia@gmail.com> [130115 10:13]:
> On Tue, Jan 15, 2013 at 3:03 PM, Tony Lindgren <tony@atomide.com> wrote:
> > * Daniel Mack <zonque@gmail.com> [130114 15:30]:
> >
> > OK thanks. Applying this set into omap-for-v3.9/gpmc.

Looks like we need ack from for one of the patches Artem before
I can push them out, replied to that patch with Artem in Cc.

> > Also sounds like Ezequiel needs to update his follow up patches accordingly.
> >
> 
> Ok, I'll do that anytime this week.

OK thanks.

Tony

^ permalink raw reply

* [PATCH 06/16] ARM: b.L: generic SMP secondary bringup and hotplug support
From: Dave Martin @ 2013-01-15 18:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMpgmWCzCxwenDs7XPh7D+shEJcj_ObWcUGZG-xMtd15XL-3Vg@mail.gmail.com>

On Tue, Jan 15, 2013 at 11:18:44AM +0000, Achin Gupta wrote:
> Hi Santosh,
> 
> On Tue, Jan 15, 2013 at 6:32 AM, Santosh Shilimkar
> <santosh.shilimkar@ti.com> wrote:
> > On Monday 14 January 2013 11:35 PM, Achin Gupta wrote:
> >>
> >> Hi Santosh,
> >>
> >> On Fri, Jan 11, 2013 at 6:02 PM, Santosh Shilimkar
> >> <santosh.shilimkar@ti.com> wrote:
> >>>
> >>> On Thursday 10 January 2013 05:50 AM, Nicolas Pitre wrote:
> >>>>
> >>>>
> >>>> Now that the b.L power API is in place, we can use it for SMP secondary
> >>>> bringup and CPU hotplug in a generic fashion.
> >>>>
> >>>> Signed-off-by: Nicolas Pitre <nico@linaro.org>
> >>>> ---
> >>>>    arch/arm/common/Makefile     |  2 +-
> >>>>    arch/arm/common/bL_platsmp.c | 79
> >>>> ++++++++++++++++++++++++++++++++++++++++++++
> >>>>    2 files changed, 80 insertions(+), 1 deletion(-)
> >>>>    create mode 100644 arch/arm/common/bL_platsmp.c
> >>>>
> >>>> diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
> >>>> index 894c2ddf9b..59b36db7cc 100644
> >>>> --- a/arch/arm/common/Makefile
> >>>> +++ b/arch/arm/common/Makefile
> >>>> @@ -15,4 +15,4 @@ obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
> >>>>    obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
> >>>>    obj-$(CONFIG_FIQ_GLUE)                += fiq_glue.o fiq_glue_setup.o
> >>>>    obj-$(CONFIG_FIQ_DEBUGGER)    += fiq_debugger.o
> >>>> -obj-$(CONFIG_BIG_LITTLE)       += bL_head.o bL_entry.o vlock.o
> >>>> +obj-$(CONFIG_BIG_LITTLE)       += bL_head.o bL_entry.o bL_platsmp.o
> >>>> vlock.o
> >>>> diff --git a/arch/arm/common/bL_platsmp.c b/arch/arm/common/bL_platsmp.c
> >>>> new file mode 100644
> >>>> index 0000000000..0acb9f4685
> >>>> --- /dev/null
> >>>> +++ b/arch/arm/common/bL_platsmp.c
> >>>> @@ -0,0 +1,79 @@
> >>>> +/*
> >>>> + * linux/arch/arm/mach-vexpress/bL_platsmp.c
> >>>> + *
> >>>> + * Created by:  Nicolas Pitre, November 2012
> >>>> + * Copyright:   (C) 2012  Linaro Limited
> >>>> + *
> >>>> + * 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.
> >>>> + *
> >>>> + * Code to handle secondary CPU bringup and hotplug for the bL power
> >>>> API.
> >>>> + */
> >>>> +
> >>>> +#include <linux/init.h>
> >>>> +#include <linux/smp.h>
> >>>> +
> >>>> +#include <asm/bL_entry.h>
> >>>> +#include <asm/smp_plat.h>
> >>>> +#include <asm/hardware/gic.h>
> >>>> +
> >>>> +static void __init simple_smp_init_cpus(void)
> >>>> +{
> >>>> +       set_smp_cross_call(gic_raise_softirq);
> >>>> +}
> >>>> +
> >>>> +static int __cpuinit bL_boot_secondary(unsigned int cpu, struct
> >>>> task_struct *idle)
> >>>> +{
> >>>> +       unsigned int pcpu, pcluster, ret;
> >>>> +       extern void secondary_startup(void);
> >>>> +
> >>>> +       pcpu = cpu_logical_map(cpu) & 0xff;
> >>>> +       pcluster = (cpu_logical_map(cpu) >> 8) & 0xff;
> >>>> +       pr_debug("%s: logical CPU %d is physical CPU %d cluster %d\n",
> >>>> +                __func__, cpu, pcpu, pcluster);
> >>>> +
> >>>> +       bL_set_entry_vector(pcpu, pcluster, NULL);
> >>>> +       ret = bL_cpu_power_up(pcpu, pcluster);
> >>>> +       if (ret)
> >>>> +               return ret;
> >>>> +       bL_set_entry_vector(pcpu, pcluster, secondary_startup);
> >>>> +       gic_raise_softirq(cpumask_of(cpu), 0);
> >>>> +       sev();
> >>>
> >>>
> >>> softirq() should be enough to break a CPU if it is in standby with
> >>> wfe state. Is that additional sev() needed here ?
> >>
> >>
> >> Not if the target cpu has its I & F bits disabled and that would be the
> >> case with a secondary waiting to be woken up
> >>
> > This is interesting since CPU is actually in standby state and this
> > was not my understanding so far. Your statement at least contradicts
> > the ARM ARM (B1.8.12 Wait For Interrupt)
> > -----------------------
> > The processor can remain in the WFI low-power state until it is reset, or it
> > detects one of the following WFI wake-up
> > events:
> > ? a physical IRQ interrupt, regardless of the value of the CPSR.I bit
> > ? a physical FIQ interrupt, regardless of the value of the CPSR.F bit
> > ----------------------------------
> >
> > Are you referring to some new behavior on latest ARMv7 CPUs ?
> 
> You are abs right about the 'wfi' behaviour. I was talking about the effect
> of interrupts on a cpu thats in 'wfe'.
> 
> The power up process takes place in two steps. The first step involves
> sending an ipi which will either:
> 
> a. cause the power controller to bring the processor out of reset
> b. cause the processor to exit from wfi (most probably in the bootloader code)
> 
> The cpu then enters Linux (bL_entry_point) and after doing any cluster setup
> waits in 'wfe' if its 'bL_entry_vector' has not been set as yet. The
> 'sev' is meant
> to poke the cpu once this has been done.
> 
> Its not required in this case as we have already set 'bL_entry_vector' , issued
> a barrier & flushed the cache line. So if the incoming cpu sees a 0 in
> its vector
> then that would be a symptom of a different problem.

Perhaps this could be made a bit clearer by defining two helpers,
bL_entry_close_gate() and bL_entry_open_gate().  The sev() is only
applicable for opening the gate, and could be buried in
bL_entry_open_gate().

This is pretty specialised low-level code though, so I'm not sure that
the abstraction is worth it.

Cheers
---Dave

^ permalink raw reply

* [PATCH v8 2/5] mtd: omap-nand: pass device_node in platform data
From: Tony Lindgren @ 2013-01-15 18:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1355481404-27695-3-git-send-email-zonque@gmail.com>

Artem,

Looks like this patch related to making GPMC work with DT was
never sent to linux-mtd or to you so adding to cc.

Is this OK to apply along with the GPMC patches, or do you want to
take this separately with the MTD patches?

Regards,

Tony

* Daniel Mack <zonque@gmail.com> [121214 02:39]:
> Pass an optional device_node pointer in the platform data, which in turn
> will be put into a mtd_part_parser_data. This way, code that sets up the
> platform devices can pass along the node from DT so that the partitions
> can be parsed.
> 
> For non-DT boards, this change has no effect.
> 
> Signed-off-by: Daniel Mack <zonque@gmail.com>
> ---
>  drivers/mtd/nand/omap2.c                     | 4 +++-
>  include/linux/platform_data/mtd-nand-omap2.h | 4 +++-
>  2 files changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> index 0002d5e..1d333497c 100644
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -1332,6 +1332,7 @@ static int omap_nand_probe(struct platform_device *pdev)
>  	dma_cap_mask_t mask;
>  	unsigned sig;
>  	struct resource			*res;
> +	struct mtd_part_parser_data	ppdata = {};
>  
>  	pdata = pdev->dev.platform_data;
>  	if (pdata == NULL) {
> @@ -1557,7 +1558,8 @@ static int omap_nand_probe(struct platform_device *pdev)
>  		goto out_release_mem_region;
>  	}
>  
> -	mtd_device_parse_register(&info->mtd, NULL, NULL, pdata->parts,
> +	ppdata.of_node = pdata->of_node;
> +	mtd_device_parse_register(&info->mtd, NULL, &ppdata, pdata->parts,
>  				  pdata->nr_parts);
>  
>  	platform_set_drvdata(pdev, &info->mtd);
> diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
> index 24d32ca..6bf9ef4 100644
> --- a/include/linux/platform_data/mtd-nand-omap2.h
> +++ b/include/linux/platform_data/mtd-nand-omap2.h
> @@ -60,6 +60,8 @@ struct omap_nand_platform_data {
>  	int			devsize;
>  	enum omap_ecc           ecc_opt;
>  	struct gpmc_nand_regs	reg;
> -};
>  
> +	/* for passing the partitions */
> +	struct device_node	*of_node;
> +};
>  #endif
> -- 
> 1.7.11.7
> 

^ permalink raw reply

* [PATCH] dmaengine: omap-dma: Allow DMA controller to prefetch data
From: Mark A. Greer @ 2013-01-15 18:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121119163727.GB9758@animalcreek.com>

On Mon, Nov 19, 2012 at 09:37:27AM -0700, Mark A. Greer wrote:
> From: "Mark A. Greer" <mgreer@animalcreek.com>
> 
> Enable DMA prefetching for non-cyclic DMAs by setting the
> 'OMAP_DMA_DST_SYNC_PREFETCH' flag when there is a destination
> synchronized DMA transfer.  Prefetching is not allowed on
> source synchronized DMA transfers.  It is not allowed on
> cyclic DMAs either since that can cause issues with some
> users (e.g., suspending/resuming audio).
> 
> CC: Russell King <rmk+kernel@arm.linux.org.uk>
> CC: P?ter Ujfalusi <peter.ujfalusi@ti.com>
> Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
> ---
>  drivers/dma/omap-dma.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
> index bb2d8e7..3932eab 100644
> --- a/drivers/dma/omap-dma.c
> +++ b/drivers/dma/omap-dma.c
> @@ -310,7 +310,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
>  		dev_addr = c->cfg.dst_addr;
>  		dev_width = c->cfg.dst_addr_width;
>  		burst = c->cfg.dst_maxburst;
> -		sync_type = OMAP_DMA_DST_SYNC;
> +		sync_type = OMAP_DMA_DST_SYNC_PREFETCH;
>  	} else {
>  		dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
>  		return NULL;
> -- 
> 1.7.12

Ping?

^ permalink raw reply

* [PATCH v3] clk: mvebu/clk-cpu.c: fix memory leakage
From: Cong Ding @ 2013-01-15 18:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50F5A1A9.2030803@free-electrons.com>

the variable cpuclk and clk_name should be properly freed when error happens.

Signed-off-by: Cong Ding <dinggnu@gmail.com>
Acked-by: Jason Cooper <jason@lakedaemon.net>
---
 drivers/clk/mvebu/clk-cpu.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
index ff004578..9dd2551 100644
--- a/drivers/clk/mvebu/clk-cpu.c
+++ b/drivers/clk/mvebu/clk-cpu.c
@@ -124,7 +124,7 @@ void __init of_cpu_clk_setup(struct device_node *node)
 
 	clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL);
 	if (WARN_ON(!clks))
-		return;
+		goto clks_out;
 
 	for_each_node_by_type(dn, "cpu") {
 		struct clk_init_data init;
@@ -134,11 +134,11 @@ void __init of_cpu_clk_setup(struct device_node *node)
 		int cpu, err;
 
 		if (WARN_ON(!clk_name))
-			return;
+			goto bail_out;
 
 		err = of_property_read_u32(dn, "reg", &cpu);
 		if (WARN_ON(err))
-			return;
+			goto bail_out;
 
 		sprintf(clk_name, "cpu%d", cpu);
 		parent_clk = of_clk_get(node, 0);
@@ -167,6 +167,9 @@ void __init of_cpu_clk_setup(struct device_node *node)
 	return;
 bail_out:
 	kfree(clks);
+	while(ncpus--)
+		kfree(cpuclk[ncpus].clk_name);
+clks_out:
 	kfree(cpuclk);
 }
 
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 07/16] ARM: bL_platsmp.c: close the kernel entry gate before hot-unplugging a CPU
From: Dave Martin @ 2013-01-15 18:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130114182604.GL23505@n2100.arm.linux.org.uk>

On Mon, Jan 14, 2013 at 06:26:04PM +0000, Russell King - ARM Linux wrote:
> On Mon, Jan 14, 2013 at 12:15:07PM -0500, Nicolas Pitre wrote:
> > The same could be said about the outer cache ops.  If a DSB is needed 
> > for their intent to be valid, then why isn't this DSB always implied by 
> > the corresponding cache op calls?
> 
> Hmm, just been thinking about this.
> 
> The L2x0 calls do contain a DSB but it's not obvious.  They hold a
> raw spinlock, and when that spinlock is dropped, we issue a dsb and
> sev instruction.
> 
> Whether the other L2 implementations do this or not I'm not sure -
> but the above is a requirement of the spinlock implementation, and
> it just happens to provide the right behaviour for L2x0.
> 
> But... we _probably_ don't want to impose that down at the L2 cache
> level of things - at least not for DMA ops, particular for the sanity
> of the scatter-list operating operations.  We really want to avoid
> doing one DSB per scatterlist entry, doing one DSB per scatterlist
> operation instead.
> 
> That does affect how the L2 cache API gets used - maybe we want to
> separate out the DMA stuff from the other users so that we can have
> dsbs in that path for non-DMA users.
> 
> Thoughts?

Perhaps the existing functions could be renamed to things like:

outer_XXX_flush_range()
outer_XXX_sync()

Where XXX is something like "batch" or "background".  Optionally these
could be declared somewhere separate to discourage non-DMA code from
using them.  Other code could still want to do batches of outer cache
operations efficiently, but I guess DMA is the main user.

Then we could provide simple non-background wrappers which also do
the appropriate CPU-side synchronisation, and provide the familiar
interface for that.

It might be less invasive to rename the new functions instead of the
old ones.  It partly depends on what proportion of existing uses
of these functions are incorrect (i.e., assume full synchronisation).

Cheers
---Dave

^ permalink raw reply

* [PATCH 3/4] pinctrl: add abx500 pinctrl driver core
From: Stephen Warren @ 2013-01-15 18:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358242984-5160-1-git-send-email-linus.walleij@stericsson.com>

On 01/15/2013 02:43 AM, Linus Walleij wrote:
> From: Patrice Chotard <patrice.chotard@st.com>
> 
> This adds the AB8500 core driver, which will be utilized by
> the follow-on drivers for different ABx500 variants.
> Sselect the driver from the DBX500_SOC, as this chip is
> powering and clocking that SoC.

> diff --git a/drivers/pinctrl/pinctrl-abx500.c b/drivers/pinctrl/pinctrl-abx500.c

> +static int abx500_gpio_get(struct gpio_chip *chip, unsigned offset)

Shouldn't this call abx500_gpio_get_bit(), just like abx500_gpio_set()
calls abx500_gpio_set_bit()?

> +static int abx500_gpio_direction_output(struct gpio_chip *chip,
> +					unsigned offset,
> +					int val)
...
> +	/* disable pull down */
...
> +	/* if supported, disable both pull down and pull up */

Why the need to override those options?

> +static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
> +		unsigned gpio)

> +	if (af.gpiosel_bit == UNUSED)
> +		return ABX500_DEFAULT;

That's odd; abx500_set_mode() seems to allow setting the mode to
something other than default even if (af.gpiosel_bit == UNUSED). Are
set_mode/get_mode actually correct inverses of each-other?

> +static int abx500_gpio_irq_init(struct abx500_pinctrl *pct)
...
> +#ifdef CONFIG_ARM
> +		set_irq_flags(irq, IRQF_VALID);
> +#else
> +		irq_set_noprobe(irq);
> +#endif

I assume that ifdef is always set one particular way?

> +static void abx500_gpio_irq_remove(struct abx500_pinctrl *pct)
...
> +#ifdef CONFIG_ARM
> +		set_irq_flags(irq, 0);
> +#endif

Same there.

> +static void abx500_pmx_disable(struct pinctrl_dev *pctldev,
> +			    unsigned function, unsigned group)
> +{
> +	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
> +	const struct abx500_pingroup *g;
> +
> +	g = &pct->soc->groups[group];
> +	if (g->altsetting < 0)
> +		return;
> +
> +	/* Poke out the mux, set the pin to some default state? */
> +	dev_dbg(pct->dev, "disable group %s, %u pins\n", g->name, g->npins);
> +}

That looks basically unimplemented, and the comment seems like a FIXME?

> +int abx500_gpio_request_enable(struct pinctrl_dev *pctldev,
> +			    struct pinctrl_gpio_range *range,
> +			    unsigned offset)
...
> +	/*
> +	 * by default, for ABx5xx family, GPIO mode is selected by
> +	 * writing 1 in GPIOSELx registers
> +	 */
> +	ret = abx500_mask_and_set_register_interruptible(pct->dev,
> +		AB8500_MISC, reg, 1 << pos, 1 << pos);

It sounds like this should be implemented using abx500_set_mode()?

> +int abx500_pin_config_set(struct pinctrl_dev *pctldev,
> +		       unsigned pin,
> +		       unsigned long config)

> +	switch (param) {
> +	case PIN_CONFIG_BIAS_PULL_DOWN:
> +		/*
> +		 * if argument = 1 set the pull down
> +		 * else clear the pull down
> +		 */
> +		ret = abx500_gpio_direction_input(chip, offset);

That looks odd; why force the pin to be a GPIO just to enable a pull down?

> +		/* check if pin supports pull updown feature */
> +		if (pullud && pin >= pullud->first_pin	&& pin <= pullud->last_pin)
> +			ret = abx500_config_pull_updown(pct,
> +				offset,
> +				argument ? ABX500_GPIO_PULL_DOWN : ABX500_GPIO_PULL_NONE);
> +		else
> +			ret = abx500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG,
> +				offset, argument ? 0 : 1);

Hmm. Wouldn't it be better to remove the if statement, and just store
ABX500_GPIO_PULL_DOWN or 0, and ABX500_GPIO_PULL_NONE or 1, in the soc_data?

> +static int __devinit abx500_gpio_probe(struct platform_device *pdev)

> +	/* Poke in other ASIC variants here */
> +	switch (platid->driver_data) {
> +	case PINCTRL_AB8500:
> +		abx500_pinctrl_ab8500_init(&pct->soc);
> +		break;
> +	case PINCTRL_AB8540:
> +		abx500_pinctrl_ab8540_init(&pct->soc);
> +		break;
> +	case PINCTRL_AB9540:
> +		abx500_pinctrl_ab9540_init(&pct->soc);
> +		break;
> +	case PINCTRL_AB8505:
> +		abx500_pinctrl_ab8505_init(&pct->soc);
> +		break;
> +	default:
> +		dev_err(&pdev->dev, "Unsupported pinctrl sub driver (%d)\n",
> +				(int) platid->driver_data);
> +		return -EINVAL;
> +	}

Most of those functions don't exist yet. I see there are dummy inlines
below for them if the /config/ options aren't turned on, but what's to
stop somebody turning on the config option before the real
implementation exists?

In the past, Arnd requested that each variant had a separate top-level
driver object that called into a utility probe() function, rather than
having a probe() function that knew about all the SoC variants, and
dispatched out to a variant-specific function.

> +static int __devexit abx500_gpio_remove(struct platform_device *pdev)

> +	platform_set_drvdata(pdev, NULL);

There's no point doing that; nothing should touch the drvdata while the
device doesn't exist (or isn't probed rather).

> +	mutex_destroy(&pct->lock);
> +	kfree(pct);

That was allocated using devm_kzalloc(). There's no point freeing it
here, and if there were, devm_kfree() should be used, or a double-free
will occur.

^ permalink raw reply

* [PATCH v2] clk: mvebu/clk-cpu.c: fix memory leakage
From: Gregory CLEMENT @ 2013-01-15 18:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130115182629.GB7211@gmail.com>

On 01/15/2013 07:26 PM, Cong Ding wrote:
> On Tue, Jan 15, 2013 at 05:33:57PM +0100, Gregory CLEMENT wrote:
>> On 01/15/2013 04:37 PM, Jason Cooper wrote:
>>> Mike,
>>>
>>> On Tue, Jan 15, 2013 at 03:23:08PM +0000, Cong Ding wrote:
>>>> From 75c73077905b822be6e8a32a09d6b0cdb5e61763 Mon Sep 17 00:00:00 2001
>>>> From: Cong Ding <dinggnu@gmail.com>
>>>> Date: Mon, 14 Jan 2013 18:06:26 +0100
>>>> Subject: [PATCH v2] clk: mvebu/clk-cpu.c: fix memory leakage
>>>>
>>>> the variable cpuclk and clk_name should be properly freed when error happens.
>>>>
>>>> Signed-off-by: Cong Ding <dinggnu@gmail.com>
>>>> ---
>>>>  drivers/clk/mvebu/clk-cpu.c |   15 ++++++++++-----
>>>>  1 file changed, 10 insertions(+), 5 deletions(-)
>>>
>>>
>>> Do you want to take this fix through the clock tree?  If so,
>>>
>>> Acked-by: Jason Cooper <jason@lakedaemon.net>
>>>
>>
>> I also think it should go through the clock tree but before this
>> I'd like we fix the last issue.
>>
>> Cong Ding,
>>
>> you didn't take in account the case when the allocation of the 1st clocks
>> when the 2nd cpu clock failed. In this case there is still a memory leak with
>> the clock_name of the first cpu clock. See below for my proposal:
>>
>>> Otherwise, just let me know.
>>>
>>> thx,
>>>
>>> Jason.
>>>
>>>> diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
>>>> index ff004578..1066a43 100644
>>>> --- a/drivers/clk/mvebu/clk-cpu.c
>>>> +++ b/drivers/clk/mvebu/clk-cpu.c
>>>> @@ -124,7 +124,7 @@ void __init of_cpu_clk_setup(struct device_node *node)
>>>>  
>>>>  	clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL);
>>>>  	if (WARN_ON(!clks))
>>>> -		return;
>>>> +		goto clks_out;
>>>>  
>>>>  	for_each_node_by_type(dn, "cpu") {
>>>>  		struct clk_init_data init;
>>>> @@ -134,11 +134,13 @@ void __init of_cpu_clk_setup(struct device_node *node)
>>>>  		int cpu, err;
>>>>  
>>>>  		if (WARN_ON(!clk_name))
>>>> -			return;
>>>> +			goto bail_out;
>>>>  
>>>>  		err = of_property_read_u32(dn, "reg", &cpu);
>>>> -		if (WARN_ON(err))
>>>> -			return;
>>>> +		if (WARN_ON(err)) {
>>
>>>> +			kfree(clk_name);
>> we can free it later
>>
>>>> +			goto bail_out;
>>>> +		}
>>>>  
>>>>  		sprintf(clk_name, "cpu%d", cpu);
>>>>  		parent_clk = of_clk_get(node, 0);
>>>> @@ -156,8 +158,10 @@ void __init of_cpu_clk_setup(struct device_node *node)
>>>>  		init.num_parents = 1;
>>>>  
>>>>  		clk = clk_register(NULL, &cpuclk[cpu].hw);
>>>> -		if (WARN_ON(IS_ERR(clk)))
>>>> +		if (WARN_ON(IS_ERR(clk))) {
>>
>>>> +			kfree(clk_name);
>> we can free it later
>>
>>>>  			goto bail_out;
>>>> +		}
>>>>  		clks[cpu] = clk;
>>>>  	}
>>>>  	clk_data.clk_num = MAX_CPU;
>>>> @@ -167,6 +171,7 @@ void __init of_cpu_clk_setup(struct device_node *node)
>>>>  	return;
>>>>  bail_out:
>>>>  	kfree(clks);
>>>> +clks_out:
>>
>> as cpuclk is allocated with all its member set to 0, and kfree(0) is a valid call.
>> We can add the following lines:
>> while(ncpus--)
>> 	kfree(cpuclk[ncpus].clk_name);
>>
>>>>  	kfree(cpuclk);
>>>>  }
> I agree the version 2 patch still includes memory leakage in terms of clk_name,
> but I am wondering whether it is safe to call kfree(cpuclk[ncpus].clkname)
> directly or not. It's true that kfree(0) is valid, but cpuclk[ncpus].clkname
> might not be 0 when it is allocated by kzalloc. kzalloc just allocates the
> memory while doesn't ensure the initial value in this memory area is 0. So I

I think that you describe the behavior of kmalloc, but the main difference
with kmalloc and kzalloc, is that kzalloc allocates _zeroed_ paged, so I am
pretty sure that all the memory space allocated should be set to zero.

> am thinking we should call memset after the alloction or use a counter to
> remember the number of clk_names allocated?
> 
> - cong
> 


-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [PATCH 13/16] drivers: misc: add ARM CCI support
From: Dave Martin @ 2013-01-15 18:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.02.1301111414390.6300@xanadu.home>

On Fri, Jan 11, 2013 at 02:22:10PM -0500, Nicolas Pitre wrote:
> On Fri, 11 Jan 2013, Santosh Shilimkar wrote:
> 
> > On Thursday 10 January 2013 05:50 AM, Nicolas Pitre wrote:
> > > From: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > > 
> > > On ARM multi-cluster systems coherency between cores running on
> > > different clusters is managed by the cache-coherent interconnect (CCI).
> > > It allows broadcasting of TLB invalidates and memory barriers and it
> > > guarantees cache coherency at system level.
> > > 
> > > This patch enables the basic infrastructure required in Linux to
> > > handle and programme the CCI component. The first implementation is
> > > based on a platform device, its relative DT compatible property and
> > > a simple programming interface.
> > > 
> > > Signed-off-by: Nicolas Pitre <nico@linaro.org>
> > > ---
> > >   drivers/misc/Kconfig    |   3 ++
> > >   drivers/misc/Makefile   |   1 +
> > >   drivers/misc/arm-cci.c  | 107
> > > ++++++++++++++++++++++++++++++++++++++++++++++++
> > >   include/linux/arm-cci.h |  30 ++++++++++++++
> > How about 'drivers/bus/' considering CCI is an interconnect bus (though
> > for coherency)
> 
> Yes, I like that better.
> 
> > >   4 files changed, 141 insertions(+)
> > >   create mode 100644 drivers/misc/arm-cci.c
> > >   create mode 100644 include/linux/arm-cci.h
> > > 
> > > diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> > > index b151b7c1bd..30d5be1ad2 100644
> > > --- a/drivers/misc/Kconfig
> > > +++ b/drivers/misc/Kconfig
> > > @@ -499,6 +499,9 @@ config USB_SWITCH_FSA9480
> > >   	  stereo and mono audio, video, microphone and UART data to use
> > >   	  a common connector port.
> > > 
> > > +config ARM_CCI
> > You might want add depends on ARM big.LITTTLE otherwise it will
> > break build for other arch's with random configurations.
> 
> As far as this patch goes, this is buildable on other architectures too.  
> The next patch changes that though.
> 
> > [..]
> > 
> > > diff --git a/drivers/misc/arm-cci.c b/drivers/misc/arm-cci.c
> > > new file mode 100644
> > > index 0000000000..f329c43099
> > > --- /dev/null
> > > +++ b/drivers/misc/arm-cci.c
> > > @@ -0,0 +1,107 @@
> > > +/*
> > > + * CCI support
> > > + *
> > > + * Copyright (C) 2012 ARM Ltd.
> > > + * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.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.
> > > + *
> > > + * 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/io.h>
> > > +#include <linux/module.h>
> > > +#include <linux/platform_device.h>
> > > +#include <linux/slab.h>
> > > +#include <linux/arm-cci.h>
> > > +
> > > +#define CCI400_EAG_OFFSET       0x4000
> > > +#define CCI400_KF_OFFSET        0x5000
> > > +
> > > +#define DRIVER_NAME	"CCI"
> > > +struct cci_drvdata {
> > > +	void __iomem *baseaddr;
> > > +	spinlock_t lock;
> > > +};
> > > +
> > > +static struct cci_drvdata *info;
> > > +
> > > +void disable_cci(int cluster)
> > > +{
> > > +	u32 cci_reg = cluster ? CCI400_KF_OFFSET : CCI400_EAG_OFFSET;
> > > +	writel_relaxed(0x0, info->baseaddr	+ cci_reg);
> > > +
> > > +	while (readl_relaxed(info->baseaddr + 0xc) & 0x1)
> > > +			;
> > > +}
> > > +EXPORT_SYMBOL_GPL(disable_cci);
> > > +
> > Is more functionality going to be added for CCI driver. Having this
> > much of driver code for just a disable_cci() functions seems like
> > overkill.
> 
> Yes.  More code will appear here to provide pmu functionalities, etc.

There's also a load of QoS configuration and other stuff which we could
control, in principle.  Normally the optimum settings are a property of
the hardware, so maybe we would always just rely on the firmware to
set up a sensible configuration.

Cheers
---Dave

^ permalink raw reply

* [PATCH 00/16] big.LITTLE low-level CPU and cluster power management
From: Dave Martin @ 2013-01-15 18:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.02.1301140849020.6300@xanadu.home>

On Mon, Jan 14, 2013 at 09:05:25AM -0500, Nicolas Pitre wrote:
> On Mon, 14 Jan 2013, Joseph Lo wrote:
> 
> > Hi Nicolas,
> > 
> > On Thu, 2013-01-10 at 08:20 +0800, Nicolas Pitre wrote:
> > > This is the initial public posting of the initial support for big.LITTLE.
> > > Included here is the code required to safely power up and down CPUs in a
> > > b.L system, whether this is via CPU hotplug, a cpuidle driver or the
> > > Linaro b.L in-kernel switcher[*] on top of this.  Only  SMP secondary
> > > boot and CPU hotplug support is included at this time.  Getting to this
> > > point already represents a significcant chunk of code as illustrated by
> > > the diffstat below.
> > > 
> > > This work was presented at Linaro Connect in Copenhagen by Dave Martin and
> > > myself.  The presentation slides are available here:
> > > 
> > > http://www.linaro.org/documents/download/f3569407bb1fb8bde0d6da80e285b832508f92f57223c
> > > 
> > > The code is now stable on both Fast Models as well as Virtual Express TC2
> > > and ready for public review.
> > > 
> > > Platform support is included for Fast Models implementing the
> > > Cortex-A15x4-A7x4 and Cortex-A15x1-A7x1 configurations.  To allow
> > > successful compilation, I also included a preliminary version of the
> > > CCI400 driver from Lorenzo Pieralisi.
> > > 
> > > Support for actual hardware such as Vexpress TC2 should come later,
> > > once the basic infrastructure from this series is merged.  A few DT
> > > bindings are used but not yet documented.
> > > 
> > > This series is made of the following parts:
> > > 
> > > Low-level support code:
> > > [PATCH 01/16] ARM: b.L: secondary kernel entry code
> > > [PATCH 02/16] ARM: b.L: introduce the CPU/cluster power API
> > > [PATCH 03/16] ARM: b.L: introduce helpers for platform coherency
> > > [PATCH 04/16] ARM: b.L: Add baremetal voting mutexes
> > > [PATCH 05/16] ARM: bL_head: vlock-based first man election
> > > 
> > > Adaptation layer to hook with the generic kernel infrastructure:
> > > [PATCH 06/16] ARM: b.L: generic SMP secondary bringup and hotplug
> > > [PATCH 07/16] ARM: bL_platsmp.c: close the kernel entry gate before
> > > [PATCH 08/16] ARM: bL_platsmp.c: make sure the GIC interface of a
> > > [PATCH 09/16] ARM: vexpress: Select the correct SMP operations at
> > > 
> > > Fast Models support:
> > > [PATCH 10/16] ARM: vexpress: introduce DCSCB support
> > > [PATCH 11/16] ARM: vexpress/dcscb: add CPU use counts to the power
> > > [PATCH 12/16] ARM: vexpress/dcscb: do not hardcode number of CPUs
> > > [PATCH 13/16] drivers: misc: add ARM CCI support
> > > [PATCH 14/16] ARM: TC2: ensure powerdown-time data is flushed from
> > > [PATCH 15/16] ARM: vexpress/dcscb: handle platform coherency
> > > [PATCH 16/16] ARM: vexpress/dcscb: probe via device tree
> > > 
> > 
> > Thanks for introducing this series.
> > I am taking a look at this series. It introduced an algorithm for
> > syncing and avoid racing when syncing the power status of clusters and
> > CPUs. Do you think these codes could have a chance to become a generic
> > framework?
> 
> Yes.  As I mentioned before, the bL_ prefix is implied only by the fact 
> that big.LITTLE was the motivation for creating this code.
> 
> > The Tegra chip series had a similar design for CPU clusters and it 
> had
> > limitation that the CPU0 always needs to be the last CPU to be shut down
> > before cluster power down as well. I believe it can also get benefits of
> > this works. We indeed need a similar algorithm to sync CPUs power status
> > before cluster power down and switching.
> > 
> > The "bL_entry.c", "bL_entry.S", "bL_entry.h", "vlock.h" and "vlock.S"
> > looks have a chance to be a common framework for ARM platform even if it
> > just support one cluster. Because some systems had the limitations for
> > cluster power down. That's why the coupled cpuidle been introduced. And
> > this framework could be enabled automatically if platform dependent or
> > by menuconfig.
> 
> Absolutely.
> 
> 
> > For ex,
> > 	select CPUS_CLUSTERS_POWER_SYNC_FRAMEWORK if SMP && CPU_PM
> > 
> > How do you think of this suggestion?
> 
> I'd prefer a more concise name though.
> 
> > BTW, some questions...
> > 1. The "bL_entry_point" looks like a first run function when CPUs just
> > power up, then jumping to original reset vector that it should be
> > called. Do you think this should be a function and be called by reset
> > handler? Or in your design, this should be called as soon as possible
> > when the CPU power be resumed?
> 
> This should be called as soon as possible.

For one thing, you can't safely turn on the MMU or do anything which may
affect any other CPU, until the code at bL_entry_point has run.

On most real hardware, the first thing to run on a powered-up CPU will
be some boot ROM or firmware, but we expect bL_entry_point to be the
initial entry point into Linux in these scenarios.

> > 2. Does the Last_man mechanism should implement in platform specific
> > code to check something like cpu_online_status and if there is a
> > limitation for the specific last CPU to be powered down?
> 
> The selection of the last man is accomplished using a platform specific 
> mechanism.  By the time this has to be done, the CPU is already dead as 
> far as the Linux kernel is concerned, and therefore the generic CPU map 
> is not reliable.  In the DCSCB case we simply look at the hardware reset 
> register being modified to directly determine the last man.  On TC2 (not 
> yet posted) we have to keep a local map of online CPUs.
> 
> In your case, the selection of the last man would simply be forced on 
> CPU0.

Things are actually simpler in your scenario, because there
is only one CPU that can possibly become the last man.  However, the
algorithm could still be re-used: it doesn't matter that it is "too
safe" for your situation, and some aspects remain important, such
as checking for CPUs unexpectedly powering up while a cluster power-
down is pending, for example.

Cheers
---Dave

^ permalink raw reply

* [PATCH 1/1] clk-divider: fix is_power_of_two()
From: Joe Perches @ 2013-01-15 18:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358245685-4392-1-git-send-email-james.hogan@imgtec.com>

On Tue, 2013-01-15 at 10:28 +0000, James Hogan wrote:
> The macro is_power_of_two() in clk-divider.c was defined as !(i & ~i)
> which is always true. Correct it to !(i & (i - 1)).
[]
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
[]
> @@ -29,8 +29,8 @@
[]
> -#define div_mask(d)	((1 << (d->width)) - 1)
> -#define is_power_of_two(i)	!(i & ~i)
> +#define div_mask(d)	((1 << ((d)->width)) - 1)
> +#define is_power_of_two(i)	(!((i) & ((i) - 1)))

Use is_power_of_2 in log2.h instead?

^ permalink raw reply

* [PATCH v2] clk: mvebu/clk-cpu.c: fix memory leakage
From: Cong Ding @ 2013-01-15 18:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50F584F5.6030007@free-electrons.com>

On Tue, Jan 15, 2013 at 05:33:57PM +0100, Gregory CLEMENT wrote:
> On 01/15/2013 04:37 PM, Jason Cooper wrote:
> > Mike,
> > 
> > On Tue, Jan 15, 2013 at 03:23:08PM +0000, Cong Ding wrote:
> >> From 75c73077905b822be6e8a32a09d6b0cdb5e61763 Mon Sep 17 00:00:00 2001
> >> From: Cong Ding <dinggnu@gmail.com>
> >> Date: Mon, 14 Jan 2013 18:06:26 +0100
> >> Subject: [PATCH v2] clk: mvebu/clk-cpu.c: fix memory leakage
> >>
> >> the variable cpuclk and clk_name should be properly freed when error happens.
> >>
> >> Signed-off-by: Cong Ding <dinggnu@gmail.com>
> >> ---
> >>  drivers/clk/mvebu/clk-cpu.c |   15 ++++++++++-----
> >>  1 file changed, 10 insertions(+), 5 deletions(-)
> > 
> > 
> > Do you want to take this fix through the clock tree?  If so,
> > 
> > Acked-by: Jason Cooper <jason@lakedaemon.net>
> > 
> 
> I also think it should go through the clock tree but before this
> I'd like we fix the last issue.
> 
> Cong Ding,
> 
> you didn't take in account the case when the allocation of the 1st clocks
> when the 2nd cpu clock failed. In this case there is still a memory leak with
> the clock_name of the first cpu clock. See below for my proposal:
> 
> > Otherwise, just let me know.
> > 
> > thx,
> > 
> > Jason.
> > 
> >> diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
> >> index ff004578..1066a43 100644
> >> --- a/drivers/clk/mvebu/clk-cpu.c
> >> +++ b/drivers/clk/mvebu/clk-cpu.c
> >> @@ -124,7 +124,7 @@ void __init of_cpu_clk_setup(struct device_node *node)
> >>  
> >>  	clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL);
> >>  	if (WARN_ON(!clks))
> >> -		return;
> >> +		goto clks_out;
> >>  
> >>  	for_each_node_by_type(dn, "cpu") {
> >>  		struct clk_init_data init;
> >> @@ -134,11 +134,13 @@ void __init of_cpu_clk_setup(struct device_node *node)
> >>  		int cpu, err;
> >>  
> >>  		if (WARN_ON(!clk_name))
> >> -			return;
> >> +			goto bail_out;
> >>  
> >>  		err = of_property_read_u32(dn, "reg", &cpu);
> >> -		if (WARN_ON(err))
> >> -			return;
> >> +		if (WARN_ON(err)) {
> 
> >> +			kfree(clk_name);
> we can free it later
> 
> >> +			goto bail_out;
> >> +		}
> >>  
> >>  		sprintf(clk_name, "cpu%d", cpu);
> >>  		parent_clk = of_clk_get(node, 0);
> >> @@ -156,8 +158,10 @@ void __init of_cpu_clk_setup(struct device_node *node)
> >>  		init.num_parents = 1;
> >>  
> >>  		clk = clk_register(NULL, &cpuclk[cpu].hw);
> >> -		if (WARN_ON(IS_ERR(clk)))
> >> +		if (WARN_ON(IS_ERR(clk))) {
> 
> >> +			kfree(clk_name);
> we can free it later
> 
> >>  			goto bail_out;
> >> +		}
> >>  		clks[cpu] = clk;
> >>  	}
> >>  	clk_data.clk_num = MAX_CPU;
> >> @@ -167,6 +171,7 @@ void __init of_cpu_clk_setup(struct device_node *node)
> >>  	return;
> >>  bail_out:
> >>  	kfree(clks);
> >> +clks_out:
> 
> as cpuclk is allocated with all its member set to 0, and kfree(0) is a valid call.
> We can add the following lines:
> while(ncpus--)
> 	kfree(cpuclk[ncpus].clk_name);
> 
> >>  	kfree(cpuclk);
> >>  }
I agree the version 2 patch still includes memory leakage in terms of clk_name,
but I am wondering whether it is safe to call kfree(cpuclk[ncpus].clkname)
directly or not. It's true that kfree(0) is valid, but cpuclk[ncpus].clkname
might not be 0 when it is allocated by kzalloc. kzalloc just allocates the
memory while doesn't ensure the initial value in this memory area is 0. So I
am thinking we should call memset after the alloction or use a counter to
remember the number of clk_names allocated?

- cong

^ permalink raw reply

* [PATCH 15/16] ARM: vexpress/dcscb: handle platform coherency exit/setup and CCI
From: Dave Martin @ 2013-01-15 18:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50F4F5D2.5000706@ti.com>

On Tue, Jan 15, 2013 at 11:53:14AM +0530, Santosh Shilimkar wrote:
> On Monday 14 January 2013 05:55 PM, Lorenzo Pieralisi wrote:
> >On Sat, Jan 12, 2013 at 07:21:24AM +0000, Santosh Shilimkar wrote:
> >>On Saturday 12 January 2013 12:58 AM, Nicolas Pitre wrote:
> >>>On Fri, 11 Jan 2013, Santosh Shilimkar wrote:
> >>>
> >>>>On Thursday 10 January 2013 05:50 AM, Nicolas Pitre wrote:
> >>>>>From: Dave Martin <dave.martin@linaro.org>
> >>>>>
> >>>>>+		/*
> >>>>>+		 * Flush the local CPU cache.
> >>>>>+		 *
> >>>>>+		 * A15/A7 can hit in the cache with SCTLR.C=0, so we don't need
> >>>>>+		 * a preliminary flush here for those CPUs.  At least, that's
> >>>>>+		 * the theory -- without the extra flush, Linux explodes on
> >>>>>+		 * RTSM (maybe not needed anymore, to be investigated).
> >>>>>+		 */
> >>>>This is expected if the entire code is not in one stack frame and the
> >>>>additional flush is needed to avoid possible stack corruption. This
> >>>>issue has been discussed in past on the list.
> >>>
> >>>I missed that.  Do you have a reference or pointer handy?
> >>>
> >>>What is strange is that this is 100% reproducible on RTSM while this
> >>>apparently is not an issue on real hardware so far.
> >>>
> >>I tried searching archives and realized the discussion was in private
> >>email thread. There are some bits and pieces on list but not all the
> >>information.
> >>
> >>The main issue RMK pointed out is- An additional L1 flush needed
> >>to avoid the effective change of view of memory when the C bit is
> >>turned off, and the cache is no longer searched for local CPU accesses.
> >>
> >>In your case dcscb_power_down() has updated the stack which can be hit
> >>in cache line and hence cache is dirty now. Then cpu_proc_fin() clears
> >>the C-bit and hence for sub sequent calls the L1 cache won't be
> >>searched. You then call flush_cache_all() which again updates the
> >>stack but avoids searching the L1 cache. So it overwrites previous
> >>saved stack frame. This seems to be an issue in your case as well.
> >
> >On A15/A7 even with the C bit cleared the D-cache is searched, the
> >situation above cannot happen and if it does we are facing a HW/model bug.
> >If this code is run on A9 then we have a problem since there, when the C bit
> >is cleared D-cache is not searched (and that's why the sequence above
> >should be written in assembly with no data access whatsoever), but on
> >A15/A7 we do not.
> >
> Good point. May be model has modeled A9 and not A15 but in either
> case, lets be consistent for all ARMv7 machines at least to avoid
> people debugging similar issues. Many machines share code for ARMv7
> processors so the best things is to stick to the sequence which works
> across all ARMv7 processors.

Is it sufficient to clarify the comment to indicate that the code is
not directly reusable for other CPU combinations?

DCSCB is incredibly platform-specific, and we would not expect to
see it in other platforms.

Or do we consider the risk of people copying this code verbatim
(including the "do not copy this code" comment) too high?

Cheers
---Dave

^ permalink raw reply

* Early kernel hang with big DTB appended
From: Nicolas Pitre @ 2013-01-15 18:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389186.eYbeMx0y73@amdc1227>

On Tue, 15 Jan 2013, Tomasz Figa wrote:

> Hi Nicolas,
> 
> On Monday 14 of January 2013 17:13:09 Nicolas Pitre wrote:
> > On Fri, 11 Jan 2013, Sascha Hauer wrote:
> > > On Thu, Jan 03, 2013 at 04:55:00PM +0100, Tomasz Figa wrote:
> > > > Hi,
> > > > 
> > > > I'm observing strange behavior when booting 3.8-rc1 and -rc2 with
> > > > appended DTB. The kernel hangs very early when the DTB is bigger
> > > > than some threshold somewhere around 24 KiB. With fullest possible
> > > > low level UART debugging (and printk patched to use printascii) I'm
> > > > receiving following output:
> > > > 
> > > > Uncompressing Linux... done, booting the kernel.
> > > > Booting Linux on physical CPU 0xa00
> > > > Linux version 3.8.0-rc1-00073-gdf6efca-dirty (t.figa at amdc1227) (gcc
> > > > version 4.5.2 (Gentoo 4.5.2 p1.2, pie-0.4.5) ) #2 SMP PREEMPT Thu
> > > > Jan 3
> > > > 15:37:35 CET 2013
> > > > CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=10c53c7d
> > > > CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction
> > > > cache
> > > > 
> > > > I tested on two Exynos-based boards (exynos4210-trats and one
> > > > internal
> > > > exynos4412-based board) and same happens on both.
> > > > 
> > > > Do you have any ideas?
> > > 
> > > Another thing besides the things already mentioned is that the dtb may
> > > not cross a 1MiB boundary. The Kernel uses a single 1Mib section
> > > (aligned to 1Mib) to initially map the dtb. Once you cross that
> > > boundary parts of the dtb won't be accessible for the Kernel anymore.
> > 
> > Crap.  You're right.  This patch should fix this issue.
> > 
> > @Tomasz: please could you confirm this fixes your initial problem?
> 
> I just tested the patch and it fixes the problem indeed. The kernel
> now boots successfully after applying the patch, while undoing it
> makes the kernel fail to boot again. Thanks.
> 
> Tested-by: Tomasz Figa <t.figa@samsung.com>

Thanks.

The patch is queued as 7628/1 in RMK's patch system.


Nicolas

^ permalink raw reply

* [PATCH 4/4] pinctrl/abx500: add AB8500 pinctrl driver
From: Stephen Warren @ 2013-01-15 18:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358242994-5200-1-git-send-email-linus.walleij@stericsson.com>

On 01/15/2013 02:43 AM, Linus Walleij wrote:
> From: Patrice Chotard <patrice.chotard@st.com>
> 
> This adds a subdriver for the AB8500 pinctrl portions.

> diff --git a/drivers/pinctrl/pinctrl-ab8500.c b/drivers/pinctrl/pinctrl-ab8500.c

> +static struct abx500_pinctrl_soc_data ab8500_ranges_soc = {
> +	.gpio_ranges = ab8500_pinranges,
> +	.gpio_num_ranges = ARRAY_SIZE(ab8500_pinranges),
> +	.pins = ab8500_ranges_pins,
> +	.npins = ARRAY_SIZE(ab8500_ranges_pins),
> +	.functions = ab8500_ranges_functions,
> +	.nfunctions = ARRAY_SIZE(ab8500_ranges_functions),
> +	.groups = ab8500_ranges_groups,
> +	.ngroups = ARRAY_SIZE(ab8500_ranges_groups),
> +	.alternate_functions = ab8500_alternate_functions,
> +	.gpio_irq_cluster = ab8500_gpio_irq_cluster,
> +	.ngpio_irq_cluster = ARRAY_SIZE(ab8500_gpio_irq_cluster),
> +	.irq_gpio_rising_offset = AB8500_INT_GPIO6R,
> +	.irq_gpio_falling_offset = AB8500_INT_GPIO6F,
> +	.irq_gpio_factor = 1,
> +};
> +
> +void __devinit
> +abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc)
> +{
> +	*soc = &ab8500_ranges_soc;
> +}

"ranges" in that variable name seems a little odd since it's much more
than ranges... But otherwise, this patch, very briefly,

Reviewed-by: Stephen Warren <swarren@nvidia.com>

^ permalink raw reply

* [PATCH v8 5/5] ARM: OMAP: gpmc: add DT bindings for GPMC timings and NAND
From: Ezequiel Garcia @ 2013-01-15 18:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130115180324.GZ14149@atomide.com>

On Tue, Jan 15, 2013 at 3:03 PM, Tony Lindgren <tony@atomide.com> wrote:
> * Daniel Mack <zonque@gmail.com> [130114 15:30]:
>> On Jan 15, 2013 2:06 AM, "Tony Lindgren" <tony@atomide.com> wrote:
>> >
>> > * Ezequiel Garcia <elezegarcia@gmail.com> [121223 13:49]:
>> > > On Fri, Dec 14, 2012 at 7:36 AM, Daniel Mack <zonque@gmail.com> wrote:
>> > > > +
>> > > > +Example for an AM33xx board:
>> > > > +
>> > > > +       gpmc: gpmc at 50000000 {
>> > > > +               compatible = "ti,am3352-gpmc";
>> > > > +               ti,hwmods = "gpmc";
>> > > > +               reg = <0x50000000 0x1000000>;
>> > > > +               interrupts = <100>;
>> > > > +               gpmc,num-cs = <8>;
>> > > > +               gpmc,num-waitpins = <2>;
>> > > > +               #address-cells = <2>;
>> > > > +               #size-cells = <1>;
>> > > > +               ranges = <0 0 0x08000000 0x2000>;       /* CS0: NAND
>> */
>> > > > +
>> > > > +               nand at 0,0 {
>> > > > +                       reg = <0 0 0>; /* CS0, offset 0 */
>> > >
>> > > I'm a bit confused by this: what are the other two values in "reg"?
>> > > I see you've only added a binding for CS.
>> > >
>> > > I've extended a bit on your work and added a binding to enable OneNAND
>> > > device on my IGEP board.
>> > >
>> > > I might send some patches in case anyone wants to give it a try.
>> >
>> > Daniel, should this be updated to just pass the CS?
>>
>> No, as Rob pointed out earlier in a thread about this topic, the 'ranges'
>> feature will help doing the math for the offset calculation eventually, so
>> we need to pass all three values.
>
> OK thanks. Applying this set into omap-for-v3.9/gpmc.
>
> Also sounds like Ezequiel needs to update his follow up patches accordingly.
>

Ok, I'll do that anytime this week.

Thanks,

-- 
    Ezequiel

^ permalink raw reply

* [PATCH v8 5/5] ARM: OMAP: gpmc: add DT bindings for GPMC timings and NAND
From: Tony Lindgren @ 2013-01-15 18:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACTFLAMT2-6VRkNSO3OF6X=afTYKRz=JcDkYqqyZ4VNT5xBVkw@mail.gmail.com>

* Daniel Mack <zonque@gmail.com> [130114 15:30]:
> On Jan 15, 2013 2:06 AM, "Tony Lindgren" <tony@atomide.com> wrote:
> >
> > * Ezequiel Garcia <elezegarcia@gmail.com> [121223 13:49]:
> > > On Fri, Dec 14, 2012 at 7:36 AM, Daniel Mack <zonque@gmail.com> wrote:
> > > > +
> > > > +Example for an AM33xx board:
> > > > +
> > > > +       gpmc: gpmc at 50000000 {
> > > > +               compatible = "ti,am3352-gpmc";
> > > > +               ti,hwmods = "gpmc";
> > > > +               reg = <0x50000000 0x1000000>;
> > > > +               interrupts = <100>;
> > > > +               gpmc,num-cs = <8>;
> > > > +               gpmc,num-waitpins = <2>;
> > > > +               #address-cells = <2>;
> > > > +               #size-cells = <1>;
> > > > +               ranges = <0 0 0x08000000 0x2000>;       /* CS0: NAND
> */
> > > > +
> > > > +               nand at 0,0 {
> > > > +                       reg = <0 0 0>; /* CS0, offset 0 */
> > >
> > > I'm a bit confused by this: what are the other two values in "reg"?
> > > I see you've only added a binding for CS.
> > >
> > > I've extended a bit on your work and added a binding to enable OneNAND
> > > device on my IGEP board.
> > >
> > > I might send some patches in case anyone wants to give it a try.
> >
> > Daniel, should this be updated to just pass the CS?
> 
> No, as Rob pointed out earlier in a thread about this topic, the 'ranges'
> feature will help doing the math for the offset calculation eventually, so
> we need to pass all three values.

OK thanks. Applying this set into omap-for-v3.9/gpmc.

Also sounds like Ezequiel needs to update his follow up patches accordingly.

Regards,

Tony

^ permalink raw reply

* [PATCH v2] mtd: vt8500: Add support for Wondermedia Serial Flash Controller
From: Tony Prisk @ 2013-01-15 17:53 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds support for the Wondermedia serial flash controller
found on WM8505, WM8650 and WM8850 SoCs.

Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
---
v2:
Change Kconfig depends to ARCH_VT8500 as this driver can't be used on other
platforms.

 drivers/mtd/devices/Kconfig      |    7 +
 drivers/mtd/devices/Makefile     |    3 +-
 drivers/mtd/devices/wmt_sflash.c |  614 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 623 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mtd/devices/wmt_sflash.c

diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 27f80cd..0233b37 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -128,6 +128,13 @@ config MTD_BCM47XXSFLASH
 	  registered by bcma as platform devices. This enables driver for
 	  serial flash memories (only read-only mode is implemented).
 
+config MTD_WMT_SFLASH
+	tristate "WonderMedia Serial Flash Support"
+	depends on ARCH_VT8500
+	help
+	  Enable this option to provide support for the Wondermedia SoC serial
+	  flash controller.
+
 config MTD_SLRAM
 	tristate "Uncached system RAM"
 	help
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 395733a..10b8bec 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_MTD_DATAFLASH)	+= mtd_dataflash.o
 obj-$(CONFIG_MTD_M25P80)	+= m25p80.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
+obj-$(CONFIG_MTD_WMT_SFLASH)	+= wmt_sflash.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
 
-CFLAGS_docg3.o			+= -I$(src)
\ No newline at end of file
+CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/wmt_sflash.c b/drivers/mtd/devices/wmt_sflash.c
new file mode 100644
index 0000000..49359ea
--- /dev/null
+++ b/drivers/mtd/devices/wmt_sflash.c
@@ -0,0 +1,614 @@
+/*
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+
+#include <linux/mtd/mtd.h>
+
+/* controller only supports erase size of 64KB */
+#define WMT_ERASESIZE			0x10000
+
+/* Serial Flash controller register offsets */
+#define SF_CHIP_SEL_0_CFG		0x000
+#define SF_CHIP_SEL_1_CFG		0x008
+#define SF_SPI_INTF_CFG			0x040
+#define SF_SPI_RD_WR_CTR		0x050
+#define SF_SPI_WR_EN_CTR		0x060
+#define SF_SPI_ER_CTR			0x070
+#define SF_SPI_ER_START_ADDR		0x074
+#define SF_SPI_ERROR_STATUS		0x080
+#define SF_SPI_MEM_0_SR_ACC		0x100
+#define SF_SPI_MEM_1_SR_ACC		0x110
+#define SF_SPI_PDWN_CTR_0		0x180
+#define SF_SPI_PDWN_CTR_1		0x190
+#define SF_SPI_PROG_CMD_CTR		0x200
+#define SF_SPI_USER_CMD_VAL		0x210
+#define SF_SPI_PROG_CMD_WBF		0x300	/* 64 bytes */
+#define SF_SPI_PROG_CMD_RBF		0x380	/* 64 bytes */
+
+/* SF_SPI_WR_EN_CTR bit fields */
+#define SF_CS0_WR_EN			BIT(0)
+#define SF_CS1_WR_EN			BIT(1)
+
+/* SF_SPI_ER_CTR bit fields */
+#define SF_SEC_ER_EN			BIT(31)
+
+/* SF_SPI_ERROR_STATUS bit fields */
+#define SF_ERR_TIMEOUT			BIT(31)
+#define SF_ERR_WR_PROT_ERR		BIT(5)
+#define SF_ERR_MEM_REGION_ERR		BIT(4)
+#define SF_ERR_PWR_DWN_ACC_ERR		BIT(3)
+#define SF_ERR_PCMD_OP_ERR		BIT(2)
+#define SF_ERR_PCMD_ACC_ERR		BIT(1)
+#define SF_ERR_MASLOCK_ERR		BIT(0)
+
+/*
+ * Serial Flash device manufacturers
+ * Please keep sorted by manufacturers ID
+ */
+#define MFR_SPANSION		0x01
+#define MFR_EON			0x1C
+#define MFR_ATMEL		0x1F
+#define MFR_NUMONYX		0x20
+#define MFR_FUDAN		0xA1
+#define MFR_SST			0xBF
+#define MFR_MXIC		0xC2
+#define MFR_WINBOND		0xEF
+
+/*
+ * SF Device Models
+ * Please keep in the same order as the manufacturers table
+ */
+
+/* Spansion */
+#define SPAN_FL016A		0x0214 /* 2 MB */
+#define SPAN_FL064A		0x0216 /* 8 MB */
+
+/* Eon */
+#define EON_25P16		0x2015 /* 2 MB */
+#define EON_25P64		0x2017 /* 8 MB */
+#define EON_25F40		0x3113 /* 512 KB */
+#define EON_25F16		0x3115 /* 2 MB */
+
+/* Atmel */
+#define AT_25DF041A		0x4401 /* 512KB */
+
+/* Numonyx */
+#define	NX_25P16		0x2015 /* 2 MB */
+#define	NX_25P64		0x2017 /* 8 MB */
+
+/* Fudan Microelectronics Group */
+#define FM_25F04		0x3113 /* 512 KB */
+
+/* SST */
+#define SST_VF016B		0x2541 /* 2 MB */
+
+/* MXIC */
+#define	MX_L512			0x2010 /* 64 KB , 4KB*/
+#define MX_L4005A		0x2013 /* 512 KB */
+#define	MX_L1605D		0x2015 /* 2 MB */
+#define	MX_L3205D		0x2016 /* 4 MB */
+#define	MX_L6405D		0x2017 /* 8 MB */
+#define	MX_L1635D		0x2415 /* 2 MB */
+#define	MX_L3235D		0x5E16 /* 4 MB */
+#define	MX_L12805D		0x2018 /* 16 MB */
+
+/* WinBond */
+#define WB_W25X40BV		0x3013	/* 512 KB */
+#define WB_X16A			0x3015	/* 2 MB */
+#define WB_X32			0x3016	/* 4 MB */
+#define WB_X64			0x3017	/* 8 MB */
+
+
+#define SF_ID(mfr, mdl)		((mfr << 16) | mdl)
+
+#define FLASH_UNKNOWN		0x00ffffff
+
+struct wmt_flash_id {
+	u32	id;
+	u32	size;		/* Size in KB */
+};
+
+static struct wmt_flash_id flash_ids[] = {
+	{ SF_ID(MFR_SPANSION,	SPAN_FL016A),	2048 },
+	{ SF_ID(MFR_SPANSION,	SPAN_FL064A),	8192 },
+	{ SF_ID(MFR_EON,	EON_25P16),	2048 },
+	{ SF_ID(MFR_EON,	EON_25P64),	8192 },
+	{ SF_ID(MFR_EON,	EON_25F40),	512 },
+	{ SF_ID(MFR_EON,	EON_25F16),	2048 },
+	{ SF_ID(MFR_ATMEL,	AT_25DF041A),	512 },
+	{ SF_ID(MFR_NUMONYX,	NX_25P16),	2048 },
+	{ SF_ID(MFR_NUMONYX,	NX_25P64),	8192 },
+	{ SF_ID(MFR_FUDAN,	FM_25F04),	512 },
+	{ SF_ID(MFR_SST,	SST_VF016B),	2048 },
+	{ SF_ID(MFR_MXIC,	MX_L512),	64 },
+	{ SF_ID(MFR_MXIC,	MX_L4005A),	512 },
+	{ SF_ID(MFR_MXIC,	MX_L1605D),	2048 },
+	{ SF_ID(MFR_MXIC,	MX_L3205D),	4192 },
+	{ SF_ID(MFR_MXIC,	MX_L6405D),	8192 },
+	{ SF_ID(MFR_MXIC,	MX_L1635D),	2048 },
+	{ SF_ID(MFR_MXIC,	MX_L3235D),	4192 },
+	{ SF_ID(MFR_MXIC,	MX_L12805D),	16384 },
+	{ SF_ID(MFR_WINBOND,	WB_W25X40BV),	512 },
+	{ SF_ID(MFR_WINBOND,	WB_X16A),	2048 },
+	{ SF_ID(MFR_WINBOND,	WB_X32),	4096 },
+	{ SF_ID(MFR_WINBOND,	WB_X64),	8192 },
+	{ 0, 0 },
+};
+
+struct wmt_sf_chip {
+	u32	id;
+	u32	size;
+	u32	addr_phys;
+	u32	ccr;
+};
+
+struct wmt_sf_data {
+	struct mtd_info		*sf_mtd;
+	struct clk		*sf_clk;
+	struct device		*dev;
+
+	struct wmt_sf_chip	chip[2];
+
+	void __iomem		*base;		/* register virt base */
+
+	void __iomem		*sf_base_virt;	/* mem-mapped sf virt base */
+	u32			sf_base_phys;	/* mem-mapped sf phys base */
+	u32			sf_total_size;
+};
+
+static u32 sf_get_chip_size(struct device *dev, u32 id)
+{
+	int i;
+	for (i = 0; flash_ids[i].id != 0; i++)
+		if (flash_ids[i].id == id)
+			return flash_ids[i].size * 1024;
+
+	dev_err(dev, "Unknown flash id (%08x)\n", id);
+	return 0;
+}
+
+static void sf_calc_ccr(struct wmt_sf_chip *chip)
+{
+	unsigned int cnt = 0, size;
+
+	size = chip->size;
+	while (size) {
+		size >>= 1;
+		cnt++;
+	}
+	cnt -= 16;
+	cnt = cnt << 8;
+	chip->ccr = (chip->addr_phys | cnt);
+}
+
+static int wmt_sf_init_hw(struct wmt_sf_data *info)
+{
+	u32 strap;
+	u32 phys_addr;
+	struct device_node *np;
+	void __iomem *gpio_base;
+
+	np = of_find_compatible_node(NULL, NULL, "wm,wm8650-gpio");
+	if (!np) {
+		dev_err(info->dev, "Unable to find GPIO node\n");
+		return -1;
+	}
+
+	gpio_base = of_iomap(np, 0);
+	if (!gpio_base) {
+		dev_err(info->dev, "Failed to map gpio memory\n");
+		return -1;
+	}
+
+	strap = readl_relaxed(gpio_base + 0x100);
+	iounmap(gpio_base);
+
+	if ((strap & 0x06) == 0) {
+		phys_addr = 0xFFFFFFFF;
+		writel(0x00000011, info->base + SF_SPI_RD_WR_CTR);
+		writel(0xFF800800, info->base + SF_CHIP_SEL_0_CFG);
+		writel(0x00030000, info->base + SF_SPI_INTF_CFG);
+	} else {
+		phys_addr = 0xEFFFFFFF;
+		writel(0x00000011, info->base + SF_SPI_RD_WR_CTR);
+		writel(0xEF800800, info->base + SF_CHIP_SEL_0_CFG);
+		writel(0x00030000, info->base + SF_SPI_INTF_CFG);
+	}
+
+	info->chip[0].id = FLASH_UNKNOWN;
+	info->chip[1].id = FLASH_UNKNOWN;
+
+	/* Read serial flash ID */
+	writel(0x11, info->base + SF_SPI_RD_WR_CTR);
+	info->chip[0].id = readl(info->base + SF_SPI_MEM_0_SR_ACC);
+	writel(0x01, info->base + SF_SPI_RD_WR_CTR);
+
+	writel(0x11, info->base + SF_SPI_RD_WR_CTR);
+	info->chip[1].id = readl(info->base + SF_SPI_MEM_1_SR_ACC);
+	writel(0x01, info->base + SF_SPI_RD_WR_CTR);
+
+	info->chip[0].size = sf_get_chip_size(info->dev, info->chip[0].id);
+	if (info->chip[0].size == 0)
+		return -1;
+
+	info->chip[0].addr_phys = phys_addr - info->chip[0].size + 1;
+	if (info->chip[0].addr_phys & 0xffff) {
+		dev_err(info->dev, "Chip 0 start address must align to 64KB\n");
+		return -1;
+	}
+	info->sf_base_phys = info->chip[0].addr_phys;
+	info->sf_total_size = info->chip[0].size;
+	pr_info("SFC: Chip 0 @ %08x (size: %d)\n", info->chip[0].addr_phys,
+							info->chip[0].size);
+
+	sf_calc_ccr(&info->chip[0]);
+	writel(info->chip[0].ccr, info->base + SF_CHIP_SEL_0_CFG);
+
+	if (info->chip[1].id != FLASH_UNKNOWN) {
+		info->chip[1].size = sf_get_chip_size(info->dev,
+						      info->chip[1].id);
+		info->chip[1].addr_phys = info->chip[0].addr_phys -
+							info->chip[1].size;
+		if (info->chip[1].addr_phys & 0xffff) {
+			dev_err(info->dev, "Chip 1 start address must align to 64KB\n");
+			info->chip[1].id = FLASH_UNKNOWN;
+			return 0;
+		}
+		info->sf_base_phys = info->chip[1].addr_phys;
+		info->sf_total_size += info->chip[1].size;
+		pr_info("SFC: Chip 1 @ %08x (size: %d)\n",
+				info->chip[1].addr_phys, info->chip[1].size);
+
+		sf_calc_ccr(&info->chip[1]);
+		writel(info->chip[1].ccr, info->base + SF_CHIP_SEL_1_CFG);
+	}
+
+	return 0;
+}
+
+static int sf_check_error(struct device *dev, u32 code)
+{
+	if (code & SF_ERR_TIMEOUT) {
+		dev_err(dev, "Serial flash timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	if (code & SF_ERR_WR_PROT_ERR) {
+		dev_err(dev, "Serial flash write-protected\n");
+		return -EIO;
+	}
+
+	if (code & SF_ERR_MEM_REGION_ERR) {
+		dev_err(dev, "Serial flash memory region error\n");
+		return -EIO;
+	}
+
+	if (code & SF_ERR_PWR_DWN_ACC_ERR) {
+		dev_err(dev, "Serial flash power down access error\n");
+		return -EIO;
+	}
+
+	if (code & SF_ERR_PCMD_OP_ERR)	{
+		dev_err(dev, "Serial flash program CMD OP error\n");
+		return -EIO;
+	}
+
+	if (code & SF_ERR_PCMD_ACC_ERR) {
+		dev_err(dev, "Serial flash program CMD OP access error\n");
+		return -EIO;
+	}
+
+	if (code & SF_ERR_MASLOCK_ERR) {
+		dev_err(dev, "Serial flash master lock error\n");
+		return -EIO;
+	}
+
+	/* no error */
+	return 0;
+}
+
+static int sf_spi_read_status(struct wmt_sf_data *info, int chip)
+{
+	u32 timeout = 0x30000000;
+	u32 temp;
+	int err;
+
+	do {
+		if (chip == 0)
+			temp = readl_relaxed(info->base + SF_SPI_MEM_0_SR_ACC);
+		else
+			temp = readl_relaxed(info->base + SF_SPI_MEM_1_SR_ACC);
+
+		if ((temp & 0x1) == 0x0)
+			break;
+
+		err = sf_check_error(info->dev,
+				     readl(info->base + SF_SPI_ERROR_STATUS));
+		if (err) {
+			writel(0x3f, info->base + SF_SPI_ERROR_STATUS);
+			return err;
+		}
+		timeout--;
+	} while (timeout);
+
+	if (timeout == 0) {
+		dev_err(info->dev, "spi request timed-out\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int sf_sector_erase(struct wmt_sf_data *info, u32 addr)
+{
+	int chip;
+	u32 val;
+
+	if ((info->sf_base_phys + addr) < info->chip[0].addr_phys) {
+		chip = 0;
+		writel(SF_CS0_WR_EN, info->base + SF_SPI_WR_EN_CTR);
+	} else {
+		chip = 1;
+		writel(SF_CS1_WR_EN, info->base + SF_SPI_WR_EN_CTR);
+	}
+
+	addr &= ~(info->sf_mtd->erasesize - 1);
+	writel(addr, info->base + SF_SPI_ER_START_ADDR);
+
+	writel(SF_SEC_ER_EN, info->base + SF_SPI_ER_CTR);
+
+	val = sf_spi_read_status(info, chip);
+
+	writel(0, info->base + SF_SPI_WR_EN_CTR);
+	return val;
+}
+
+static int sf_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct wmt_sf_data *info = mtd->priv;
+	int ret;
+
+	ret = clk_enable(info->sf_clk);
+	if (ret)
+		return ret;
+
+	ret = sf_sector_erase(info, (u32)instr->addr);
+	if (ret) {
+		clk_disable(info->sf_clk);
+		return ret;
+	}
+
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	clk_disable(info->sf_clk);
+	return 0;
+}
+
+static int sf_read(struct mtd_info *mtd, loff_t from, size_t len,
+			 size_t *retlen, u_char *buf)
+{
+	struct wmt_sf_data *info = mtd->priv;
+	int ret;
+
+	ret = clk_enable(info->sf_clk);
+	if (ret)
+		return ret;
+
+	if (sf_spi_read_status(info, 0))
+		return -EBUSY;
+	if (sf_spi_read_status(info, 1))
+		return -EBUSY;
+
+	if (from + len > mtd->size) {
+		dev_err(info->dev, "Request out of bounds (from=%llu, len=%d)\n",
+								from, len);
+		return -EINVAL;
+	}
+
+	memcpy_fromio(buf, info->sf_base_virt + from, len);
+	*retlen = len;
+
+	clk_disable(info->sf_clk);
+	return 0;
+}
+
+static int sf_sector_write(struct wmt_sf_data *info, loff_t to, size_t len,
+			   const u_char *buf)
+{
+	int ret;
+	int data_size;
+	u32 count;
+	u32 addr_to = (u32)(info->sf_base_virt) + to;
+
+	ret = clk_enable(info->sf_clk);
+	if (ret)
+		return ret;
+
+	if (sf_spi_read_status(info, 0))
+		return -EBUSY;
+	if (sf_spi_read_status(info, 1))
+		return -EBUSY;
+
+	writel(SF_CS0_WR_EN | SF_CS1_WR_EN, info->base + SF_SPI_WR_EN_CTR);
+
+	count = 0;
+	while (len) {
+		data_size = (len >= 4) ? 4 : 1;
+		memcpy_toio(((u_char *)(addr_to + count)), buf + count,
+								data_size);
+		count += data_size;
+		len -= data_size;
+
+		if (len) {
+			data_size = (len >= 4) ? 4 : 1;
+			memcpy_toio(((u_char *)(addr_to + count)), buf + count,
+								data_size);
+			count += data_size;
+			len -= data_size;
+		}
+
+		ret = sf_spi_read_status(info, 0);
+		if (ret) {
+			clk_disable(info->sf_clk);
+			return ret;
+		}
+	}
+
+	writel(0, info->base + SF_SPI_WR_EN_CTR);
+
+	clk_disable(info->sf_clk);
+
+	return count;
+}
+
+static int sf_write(struct mtd_info *mtd, loff_t to, size_t len,
+				size_t *retlen, const u_char *buf)
+{
+	struct wmt_sf_data *info = mtd->priv;
+
+	*retlen = sf_sector_write(info, to, len, buf);
+
+	return 0;
+}
+
+static int mtdsf_init_device(struct device *dev, struct mtd_info *mtd,
+					unsigned long size, char *name)
+{
+	mtd->name = name;
+	mtd->type = MTD_NORFLASH;
+	mtd->flags = MTD_CAP_NORFLASH;
+	mtd->size = size;
+	mtd->erasesize = WMT_ERASESIZE;
+	mtd->owner = THIS_MODULE;
+	mtd->_erase = sf_erase;
+	mtd->_read = sf_read;
+	mtd->_write = sf_write;
+	mtd->writesize = 1;
+
+	if (mtd_device_register(mtd, NULL, 0)) {
+		dev_err(dev, "Erroring adding MTD device\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int wmt_sf_probe(struct platform_device *pdev)
+{
+	struct wmt_sf_data	*info;
+	struct device_node	*np = pdev->dev.of_node;
+	int err;
+
+	if (!np) {
+		dev_err(&pdev->dev, "Invalid devicetree node\n");
+		return -EINVAL;
+	}
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		dev_err(&pdev->dev, "Failed to get memory for SF info\n");
+		return -ENOMEM;
+	}
+
+	info->dev = &pdev->dev;
+
+	info->base = of_iomap(np, 0);
+	if (!info->base) {
+		dev_err(&pdev->dev, "Failed to map register memory\n");
+		return -ENOMEM;
+	}
+
+	info->sf_clk = of_clk_get(np, 0);
+	if (!info->sf_clk) {
+		dev_err(&pdev->dev, "Failed to get clock from device tree\n");
+		return -EINVAL;
+	}
+
+	err = clk_prepare_enable(info->sf_clk);
+	if (err)
+		return err;
+
+	err = wmt_sf_init_hw(info);
+	clk_disable(info->sf_clk);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to initialize SF hardware\n");
+		return -EIO;
+	}
+
+	info->sf_base_virt = devm_ioremap(&pdev->dev, info->sf_base_phys,
+					  info->sf_total_size);
+	if (!info->sf_base_virt) {
+		dev_err(&pdev->dev, "Failed to map serial flash memory\n");
+		return -ENOMEM;
+	}
+
+	info->sf_mtd = devm_kzalloc(&pdev->dev, sizeof(struct mtd_info),
+								GFP_KERNEL);
+	if (!info->sf_mtd) {
+		dev_err(&pdev->dev, "Failed to allocate SFMTD memory\n");
+		return -ENOMEM;
+	}
+
+	err = mtdsf_init_device(info->dev, info->sf_mtd, info->sf_total_size,
+						"Wondermedia SF Device");
+	if (err)
+		return err;
+
+	info->sf_mtd->priv = info;
+	dev_set_drvdata(&pdev->dev, info);
+
+	pr_info("Wondermedia Serial Flash Controller initialized\n");
+
+	return 0;
+}
+
+static int wmt_sf_remove(struct platform_device *pdev)
+{
+	struct wmt_sf_data *info = dev_get_drvdata(&pdev->dev);
+
+	mtd_device_unregister(info->sf_mtd);
+
+	return 0;
+}
+
+static const struct of_device_id wmt_dt_ids[] = {
+	{ .compatible = "wm,wm8505-sf", },
+	{}
+};
+
+static struct platform_driver wmt_sf_driver = {
+	.probe		= wmt_sf_probe,
+	.remove		= wmt_sf_remove,
+	.driver		= {
+		.name	= "wmt-sf",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(wmt_dt_ids),
+	},
+};
+
+module_platform_driver(wmt_sf_driver);
+
+MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
+MODULE_DESCRIPTION("Wondermedia SoC Serial Flash driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2] mm: dmapool: use provided gfp flags for all dma_alloc_coherent() calls
From: Greg KH @ 2013-01-15 17:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130115165642.GA25500@titan.lakedaemon.net>

On Tue, Jan 15, 2013 at 11:56:42AM -0500, Jason Cooper wrote:
> Greg,
> 
> I've added you to the this thread hoping for a little insight into USB
> drivers and their use of coherent and GFP_ATOMIC.  Am I barking up the
> wrong tree by looking a the drivers?

I don't understand, which drivers are you referring to?  USB host
controller drivers, or the "normal" drivers?  Most USB drivers use
GFP_ATOMIC if they are creating memory during their URB callback path,
as that is interrupt context.  But it shouldn't be all that bad, and the
USB core hasn't changed in a while, so something else must be causing
this.

greg k-h

^ permalink raw reply

* [PATCHv4 14/14] ARM: arch_timers: switch to physical timers if HYP mode is available
From: Mark Rutland @ 2013-01-15 17:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358271931-7761-1-git-send-email-mark.rutland@arm.com>

From: Marc Zyngier <Marc.Zyngier@arm.com>

If we're booted in HYP mode, it is possible that we'll run some
kind of virtualized environment. In this case, it is a better to
switch to the physical timers, and leave the virtual timers to
guests.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
---
 drivers/clocksource/arm_arch_timer.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index ec30a73..d7ad425 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 
 #include <asm/arch_timer.h>
+#include <asm/virt.h>
 
 #include <clocksource/arm_arch_timer.h>
 
@@ -364,10 +365,14 @@ int __init arch_timer_init(void)
 	of_node_put(np);
 
 	/*
+	 * If HYP mode is available, we know that the physical timer
+	 * has been configured to be accessible from PL1. Use it, so
+	 * that a guest can use the virtual timer instead.
+	 *
 	 * If no interrupt provided for virtual timer, we'll have to
 	 * stick to the physical timer. It'd better be accessible...
 	 */
-	if (!arch_timer_ppi[VIRT_PPI]) {
+	if (is_hyp_mode_available() || !arch_timer_ppi[VIRT_PPI]) {
 		arch_timer_use_virtual = false;
 
 		if (!arch_timer_ppi[PHYS_SECURE_PPI] ||
-- 
1.7.0.4

^ permalink raw reply related

* [PATCHv4 13/14] Documentation: Add ARMv8 to arch_timer devicetree
From: Mark Rutland @ 2013-01-15 17:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358271931-7761-1-git-send-email-mark.rutland@arm.com>

Currently the documentation for the arch_timer devicetree binding only
lists "arm,armv7-timer".

Add "arm,armv8-timer" to the list of compatible strings.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 .../devicetree/bindings/arm/arch_timer.txt         |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
index 52478c8..20746e5 100644
--- a/Documentation/devicetree/bindings/arm/arch_timer.txt
+++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
@@ -1,13 +1,14 @@
 * ARM architected timer
 
-ARM Cortex-A7 and Cortex-A15 have a per-core architected timer, which
-provides per-cpu timers.
+ARM cores may have a per-core architected timer, which provides per-cpu timers.
 
 The timer is attached to a GIC to deliver its per-processor interrupts.
 
 ** Timer node properties:
 
-- compatible : Should at least contain "arm,armv7-timer".
+- compatible : Should at least contain one of
+	"arm,armv7-timer"
+	"arm,armv8-timer"
 
 - interrupts : Interrupt list for secure, non-secure, virtual and
   hypervisor timers, in that order.
-- 
1.7.0.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox