* [PATCH 1/3] serial: mxs-auart: distinguish the different SOCs
From: Huang Shijie @ 2012-10-16 6:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350367386-7742-1-git-send-email-b32955@freescale.com>
From: Huang Shijie <shijie8@gmail.com>
The current mxs-auart driver is used for both mx23 and mx28.
But in mx23, the DMA has a bug(see errata:2836). We can not add the
DMA support in mx23, but we can add DMA support to auart in mx28.
So in order to add the DMA support for the auart in mx28, we should add
the platform_device_id to distinguish the distinguish SOCs.
Signed-off-by: Huang Shijie <b32955@freescale.com>
---
.../bindings/tty/serial/fsl-mxs-auart.txt | 2 +-
arch/arm/boot/dts/imx28.dtsi | 10 +++---
drivers/tty/serial/mxs-auart.c | 28 +++++++++++++++----
3 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt b/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
index 2ee903f..a154bf1 100644
--- a/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
+++ b/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
@@ -8,7 +8,7 @@ Required properties:
Example:
auart0: serial at 8006a000 {
- compatible = "fsl,imx28-auart", "fsl,imx23-auart";
+ compatible = "fsl,imx28-auart";
reg = <0x8006a000 0x2000>;
interrupts = <112 70 71>;
};
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index e16d631..6ed9215 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -795,7 +795,7 @@
};
auart0: serial at 8006a000 {
- compatible = "fsl,imx28-auart", "fsl,imx23-auart";
+ compatible = "fsl,imx28-auart";
reg = <0x8006a000 0x2000>;
interrupts = <112 70 71>;
clocks = <&clks 45>;
@@ -803,7 +803,7 @@
};
auart1: serial at 8006c000 {
- compatible = "fsl,imx28-auart", "fsl,imx23-auart";
+ compatible = "fsl,imx28-auart";
reg = <0x8006c000 0x2000>;
interrupts = <113 72 73>;
clocks = <&clks 45>;
@@ -811,7 +811,7 @@
};
auart2: serial at 8006e000 {
- compatible = "fsl,imx28-auart", "fsl,imx23-auart";
+ compatible = "fsl,imx28-auart";
reg = <0x8006e000 0x2000>;
interrupts = <114 74 75>;
clocks = <&clks 45>;
@@ -819,7 +819,7 @@
};
auart3: serial at 80070000 {
- compatible = "fsl,imx28-auart", "fsl,imx23-auart";
+ compatible = "fsl,imx28-auart";
reg = <0x80070000 0x2000>;
interrupts = <115 76 77>;
clocks = <&clks 45>;
@@ -827,7 +827,7 @@
};
auart4: serial at 80072000 {
- compatible = "fsl,imx28-auart", "fsl,imx23-auart";
+ compatible = "fsl,imx28-auart";
reg = <0x80072000 0x2000>;
interrupts = <116 78 79>;
clocks = <&clks 45>;
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 6db3baa..cd9ec1d 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -37,6 +37,11 @@
#include <asm/cacheflush.h>
+/* Use the platform_id to distinguish different Archs. */
+#define IS_MX23 0x0
+#define IS_MX28 0x1
+#define AUART_IS_MX23(x) ((x)->pdev->id_entry->driver_data == IS_MX23)
+
#define MXS_AUART_PORTS 5
#define AUART_CTRL0 0x00000000
@@ -124,6 +129,7 @@ struct mxs_auart_port {
struct clk *clk;
struct device *dev;
+ struct platform_device *pdev;
};
static void mxs_auart_stop_tx(struct uart_port *u);
@@ -680,6 +686,19 @@ static struct uart_driver auart_driver = {
#endif
};
+static const struct platform_device_id auart_ids[] = {
+ { .name = "imx23-auart", .driver_data = IS_MX23, },
+ { .name = "imx28-auart", .driver_data = IS_MX28, },
+ {},
+};
+
+static struct of_device_id mxs_auart_dt_ids[] = {
+ { .compatible = "fsl,imx23-auart", .data = (void *)&auart_ids[0] },
+ { .compatible = "fsl,imx28-auart", .data = (void *)&auart_ids[1] },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
+
/*
* This function returns 1 if pdev isn't a device instatiated by dt, 0 if it
* could successfully get all information from dt or a negative errno.
@@ -701,6 +720,8 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
}
s->port.line = ret;
+ pdev->id_entry = of_match_device(mxs_auart_dt_ids, &pdev->dev)->data;
+
return 0;
}
@@ -753,6 +774,7 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
s->flags = 0;
s->ctrl = 0;
+ s->pdev = pdev;
s->irq = platform_get_irq(pdev, 0);
s->port.irq = s->irq;
@@ -805,12 +827,6 @@ static int __devexit mxs_auart_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id mxs_auart_dt_ids[] = {
- { .compatible = "fsl,imx23-auart", },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
-
static struct platform_driver mxs_auart_driver = {
.probe = mxs_auart_probe,
.remove = __devexit_p(mxs_auart_remove),
--
1.7.0.4
^ permalink raw reply related
* [PATCH 0/3] serial: mxs-auart: add DMA support for auart in mx28
From: Huang Shijie @ 2012-10-16 6:03 UTC (permalink / raw)
To: linux-arm-kernel
This patch set adds the DMA support for auart in mx28.
patch 1:
But in mx23, the DMA has a bug(see errata:2836). We can not add the
DMA support in mx23, but we can add DMA support to auart in mx28.
So in order to add the DMA support for the auart in mx28, we should add
the platform_device_id to distinguish the distinguish SOCs.
patch 2: add the DMA support for mx28
Only we meet the following conditions, we can enable the DMA support
for auart:
(1) We enable the DMA support in the dts file, such as
arch/arm/boot/dts/imx28.dtsi.
(2) We enable the hardware flow control.
(3) We use the mx28, not the mx23. Due to hardware bug(see errata: 2836),
we can not add the DMA support to mx23.
patch 3: enable the DMA support in dts for mx28
You can use the /ttyAPP0 to test this patch set.
I tested this patch in mx28-evk board.
Huang Shijie (3):
serial: mxs-auart: distinguish the different SOCs
serial: mxs-auart: add the DMA support for mx28
ARM: dts: enable dma support for auart0 in mx28
.../bindings/tty/serial/fsl-mxs-auart.txt | 9 +-
arch/arm/boot/dts/imx28.dtsi | 12 +-
drivers/tty/serial/mxs-auart.c | 335 +++++++++++++++++++-
3 files changed, 341 insertions(+), 15 deletions(-)
^ permalink raw reply
* dma_alloc_coherent fails in framebuffer
From: Tony Prisk @ 2012-10-16 5:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAA_GA1cPE+m8N1LQA2iOym4jbFwcHG+K2p-3iBovPWuf1N1q+g@mail.gmail.com>
On Tue, 2012-10-16 at 10:17 +0800, Bob Liu wrote:
> On Tue, Oct 16, 2012 at 2:28 AM, Tony Prisk <linux@prisktech.co.nz> wrote:
> > On Mon, 2012-10-15 at 10:45 +0100, Mel Gorman wrote:
> >> On Mon, Oct 15, 2012 at 09:34:55AM +1300, Tony Prisk wrote:
> >> > On Sun, 2012-10-14 at 18:28 +1300, Tony Prisk wrote:
> >> > > Up until 07 Oct, drivers/video/wm8505-fb.c was working fine, but on the
> >> > > 11 Oct when I did another pull from linus all of a sudden
> >> > > dma_alloc_coherent is failing to allocate the framebuffer any longer.
> >> > >
> >> > > I did a quick look back and found this:
> >> > >
> >> > > ARM: add coherent dma ops
> >> > >
> >> > > arch_is_coherent is problematic as it is a global symbol. This
> >> > > doesn't work for multi-platform kernels or platforms which can support
> >> > > per device coherent DMA.
> >> > >
> >> > > This adds arm_coherent_dma_ops to be used for devices which connected
> >> > > coherently (i.e. to the ACP port on Cortex-A9 or A15). The arm_dma_ops
> >> > > are modified at boot when arch_is_coherent is true.
> >> > >
> >> > > Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> >> > > Cc: Russell King <linux@arm.linux.org.uk>
> >> > > Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> >> > > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> >> > >
> >> > >
> >> > > This is the only patch lately that I could find (not that I would claim
> >> > > to be any good at finding things) that is related to the problem. Could
> >> > > it have caused the allocations to fail?
> >> > >
> >> > > Regards
> >> > > Tony P
> >> >
> >> > Have done a bit more digging and found the cause - not Rob's patch so
> >> > apologies.
> >> >
> >> > The cause of the regression is this patch:
> >> >
> >> > From f40d1e42bb988d2a26e8e111ea4c4c7bac819b7e Mon Sep 17 00:00:00 2001
> >> > From: Mel Gorman <mgorman@suse.de>
> >> > Date: Mon, 8 Oct 2012 16:32:36 -0700
> >> > Subject: [PATCH 2/3] mm: compaction: acquire the zone->lock as late as
> >> > possible
> >> >
> >> > Up until then, the framebuffer allocation with dma_alloc_coherent(...)
> >> > was fine. From this patch onwards, allocations fail.
> >> >
> >>
> >> Was this found through bisection or some other means?
> >>
> >> There was a bug in that series that broke CMA but it was commit bb13ffeb
> >> (mm: compaction: cache if a pageblock was scanned and no pages were
> >> isolated) and it was fixed by 62726059 (mm: compaction: fix bit ranges
> >> in {get,clear,set}_pageblock_skip()). So it should have been fixed by
> >> 3.7-rc1 and probably was included by the time you pulled in October 11th
> >> but bisection would be a pain. There were problems with that series during
> >> development but tests were completing for other people.
> >>
> >> Just in case, is this still broken in 3.7-rc1?
> >
> > Still broken. Although the printk's might have cleared it up a bit.
> >>
> >> > I don't know how this patch would effect CMA allocations, but it seems
> >> > to be causing the issue (or at least, it's caused an error in
> >> > arch-vt8500 to become visible).
> >> >
> >> > Perhaps someone who understand -mm could explain the best way to
> >> > troubleshoot the cause of this problem?
> >> >
> >>
> >> If you are comfortable with ftrace, it can be used to narrow down where
> >> the exact failure is occurring but if you're not comfortable with that
> >> then the easiest is a bunch of printks starting in alloc_contig_range()
> >> to see at what point and why it returns failure.
> >>
> >> It's not obvious at the moment why that patch would cause an allocation
> >> problem. It's the type of patch that if it was wrong it would fail every
> >> time for everyone, not just for a single driver.
> >>
> >
> > I added some printk's to see what was happening.
> >
> > from arch/arm/mm/dma-mapping.c: arm_dma_alloc(..) it calls out to:
> > dma_alloc_from_coherent().
> >
> > This returns 0, because:
> > mem = dev->dma_mem
> > if (!mem) return 0;
> >
> > and then arm_dma_alloc() falls back on __dma_alloc(..)
> >
> >
> > I suspect the reason this fault is a bit 'weird' is because its
> > effectively not using alloc_from_coherent at all, but falling back on
> > __dma_alloc all the time, and sometimes it fails.
> >
>
> I think you need to declare that memory using
> dma_declare_coherent_memory() before
> alloc_from_coherent.
>
> > Why it caused a problem on that particular commit I don't know - but it
> > was reproducible by adding/removing it.
> >
> >
> > Regards
> > Tony P
> >
> > --
> > To unsubscribe, send a message with 'unsubscribe linux-mm' in
> > the body to majordomo at kvack.org. For more info on Linux MM,
> > see: http://www.linux-mm.org/ .
> > Don't email: <a href=mailto:"dont@kvack.org"> email at kvack.org </a>
>
I finally found the link to this patch which caused the problem - and
may still be the cause of my problems :)
> >>>
> >>> From f40d1e42bb988d2a26e8e111ea4c4c7bac819b7e Mon Sep 17 00:00:00 2001
> >>> From: Mel Gorman <mgorman@suse.de>
> >>> Date: Mon, 8 Oct 2012 16:32:36 -0700
> >>> Subject: [PATCH 2/3] mm: compaction: acquire the zone->lock as late as
> >>> possible
In mm/page_alloc.c:alloc_contig_range()
...
outer_end = isolate_freepages_range(&cc, outer_start, end);
if (!outer_end) {
ret = -EBUSY;
goto done;
}
..
It is always returning via the !outer_end test with -EBUSY.
isolate_freepages_range() was one of the functions modified by
the above mentioned patch.
Around in a big circle and back to the start :)
Regards
Tony P
^ permalink raw reply
* [PATCH v2 09/13] ARM: davinci - update the dm644x soc code to use common clk drivers
From: Sekhar Nori @ 2012-10-16 5:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3E54258959B69E4282D79E01AB1F32B704201DE5@DFLE12.ent.ti.com>
Hi Murali,
On 10/15/2012 9:21 PM, Karicheri, Muralidharan wrote:
> --Cut----
>
>>> Subject: Re: [PATCH v2 09/13] ARM: davinci - update the dm644x soc code to use
>>> common clk drivers
>>>
>>>>>> You have chosen to keep all clock related data in platform files
>>>>>> while using the common clock framework to provide just the
>>>>>> infrastructure. If you look at how mxs and spear have been migrated, they have
>>> migrated the soc specific clock data to drivers/clk as well.
>>>>>> See "drivers/clk/spear/spear3xx_clock.c" or
>>>>>> "drivers/clk/mxs/clk-imx23.c
>>>>
>>>> I have to disagree on this one. I had investigated these code already
>>>> and came up with a way that we can re-use code across all of the
>>>> davinci platforms as well as other architectures that re-uses the clk hardware IPs.
>>>
>>> Which code you are talking about here? Even if you introduce clk-dm644x.c, clk-
>>> keystone.c etc in drivers/clk/davinci/ you can reuse the code you introduce in patches 1-
>>> 3. I cant see how that will be prevented.
>
> I was talking about re-use of davinci_common_clk_init in drivers/clk/davinci/davinci-clock.c.
> This is meant to be re-used across all of the DaVinci devices.
>
>>>
>>>> spear3xx_clock.c has initialization code for each of the platforms and
>>>> so is the case with imx23.c.
>>>
>>> By each of the platforms, you mean they all cater to a family of devices? This depends on
>>> how close together the family of devices are.
>>> Otherwise, there would be a file per soc. DM644x also represents a family for that matter.
>>>
>>>> By using platform_data approach, we are able to define clks for each of the SoC and
>>> then use davinci_common_clk_init() to do initialize the clk drivers based on platform
>>> data.
>>>
>>> You need to define and register the clocks present on each SoC either which way. I don't
>>> see why just the platform_data approach allows this.
>>> And looking closely, you have defined platform data, but don't actually have a platform
>>> device, making things more confusing.
>>>
>
> Ok. There are multiple ways to implement this software. We had discussed this
> internally and picked the platform_data approach. The clk drivers are written not
> following the platform driver model. But I don't see why we can't use platform data
> to configure this drivers. Down below, you have made two interesting points, one is
> ARM code reduction. This patch already does this by moving the API that initializes
> the clk drivers (davinci_common_clk_init()) out of ARM to drivers/clk/davinci. So
> this + removal of existing clk driver under arm/mach-davinci/clock.[ch], we have
> achieved this goal. The second point is the moving of SoC specific clk data out of SoC
> code to drive. Are you 100% sure this is the right thing to do for these drivers. If so,
> I can start working on this change right away. As I am working on this as a background
> activity, I want to be double or triple sure before doing the rework of these patches :).
> So please confirm.
Yes, this is the right way to go. And I don't see it as something
breaking new ground since there are already multiple SoCs in mainline
which are following this same approach. May be to start with just
convert one SoC and send for review.
Thanks for taking this up and helping clean-up mach-davinci.
Regards,
Sekhar
^ permalink raw reply
* [PATCHv6 01/11] ARM: OMAP: clockdomain: Fix locking on _clkdm_clk_hwmod_enable / disable
From: Paul Walmsley @ 2012-10-16 5:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1348589142-11983-2-git-send-email-t-kristo@ti.com>
On Tue, 25 Sep 2012, Tero Kristo wrote:
> Previously the code only acquired spinlock after increasing / decreasing
> the usecount value, which is wrong. This leaves a small window where
> a task switch may occur between the check of the usecount and the actual
> wakeup / sleep of the domain. Fixed by moving the spinlock locking before
> the usecount access. Left the usecount as atomic_t if someone wants an
> easy access to the parameter through atomic_read.
>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
Thanks, queued for 3.7-rc fixes.
- Paul
^ permalink raw reply
* [PATCH] usb: phy: samsung: Introducing usb phy driver for hsotg
From: Praveen Paneri @ 2012-10-16 5:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121015132836.GT24333@arwen.pp.htv.fi>
On Mon, Oct 15, 2012 at 6:58 PM, Felipe Balbi <balbi@ti.com> wrote:
> On Fri, Oct 12, 2012 at 03:45:34PM +0530, Praveen Paneri wrote:
>> platform_set_drvdata() required for driver's remove function, so adding
>> it back.
>>
>> From v6:
>> Added TODO for phy bindings with controller
>> Dropped platform_set_drvdata() from driver probe
>>
>> This driver uses usb_phy interface to interact with s3c-hsotg. Supports
>> phy_init and phy_shutdown functions to enable/disable phy. Tested with
>> smdk6410 and smdkv310. More SoCs can be brought under later.
>>
>
> this commit log needs improvement. There are stuff there which shouldn't
> go to git's history.
I will resend the patches with improved commit log.
Thanks,
Praveen
>
> I would like to get Tested-bys and Acked-by from DT maintainers.
>
>> Signed-off-by: Praveen Paneri <p.paneri@samsung.com>
>> Acked-by: Heiko Stuebner <heiko@sntech.de>
>> ---
>> .../devicetree/bindings/usb/samsung-usbphy.txt | 11 +
>> drivers/usb/phy/Kconfig | 8 +
>> drivers/usb/phy/Makefile | 1 +
>> drivers/usb/phy/samsung-usbphy.c | 357 ++++++++++++++++++++
>> include/linux/platform_data/samsung-usbphy.h | 27 ++
>> 5 files changed, 404 insertions(+), 0 deletions(-)
>> create mode 100644 Documentation/devicetree/bindings/usb/samsung-usbphy.txt
>> create mode 100644 drivers/usb/phy/samsung-usbphy.c
>> create mode 100644 include/linux/platform_data/samsung-usbphy.h
>>
>> diff --git a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
>> new file mode 100644
>> index 0000000..7b26e2d
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
>> @@ -0,0 +1,11 @@
>> +* Samsung's usb phy transceiver
>> +
>> +The Samsung's phy transceiver is used for controlling usb otg phy for
>> +s3c-hsotg usb device controller.
>> +TODO: Adding the PHY binding with controller(s) according to the under
>> +developement generic PHY driver.
>> +
>> +Required properties:
>> +- compatible : should be "samsung,exynos4210-usbphy"
>> +- reg : base physical address of the phy registers and length of memory mapped
>> + region.
>> diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
>> index 63c339b..313685f 100644
>> --- a/drivers/usb/phy/Kconfig
>> +++ b/drivers/usb/phy/Kconfig
>> @@ -32,3 +32,11 @@ config MV_U3D_PHY
>> help
>> Enable this to support Marvell USB 3.0 phy controller for Marvell
>> SoC.
>> +
>> +config SAMSUNG_USBPHY
>> + bool "Samsung USB PHY controller Driver"
>> + depends on USB_S3C_HSOTG
>> + select USB_OTG_UTILS
>> + help
>> + Enable this to support Samsung USB phy controller for samsung
>> + SoCs.
>> diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
>> index b069f29..55dcfc1 100644
>> --- a/drivers/usb/phy/Makefile
>> +++ b/drivers/usb/phy/Makefile
>> @@ -8,3 +8,4 @@ obj-$(CONFIG_OMAP_USB2) += omap-usb2.o
>> obj-$(CONFIG_USB_ISP1301) += isp1301.o
>> obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o
>> obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o
>> +obj-$(CONFIG_SAMSUNG_USBPHY) += samsung-usbphy.o
>> diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c
>> new file mode 100644
>> index 0000000..14c182f
>> --- /dev/null
>> +++ b/drivers/usb/phy/samsung-usbphy.c
>> @@ -0,0 +1,357 @@
>> +/* linux/drivers/usb/phy/samsung-usbphy.c
>> + *
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * http://www.samsung.com
>> + *
>> + * Author: Praveen Paneri <p.paneri@samsung.com>
>> + *
>> + * Samsung USB2.0 High-speed OTG transceiver, talks to S3C HS OTG controller
>> + *
>> + * 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 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/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/clk.h>
>> +#include <linux/delay.h>
>> +#include <linux/err.h>
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/usb/otg.h>
>> +#include <linux/platform_data/samsung-usbphy.h>
>> +
>> +/* Register definitions */
>> +
>> +#define S3C_PHYPWR (0x00)
>> +
>> +#define S3C_PHYPWR_NORMAL_MASK (0x19 << 0)
>> +#define S3C_PHYPWR_OTG_DISABLE (1 << 4)
>> +#define S3C_PHYPWR_ANALOG_POWERDOWN (1 << 3)
>> +#define S3C_PHYPWR_FORCE_SUSPEND (1 << 1)
>> +/* For Exynos4 */
>> +#define EXYNOS4_PHYPWR_NORMAL_MASK (0x39 << 0)
>> +#define EXYNOS4_PHYPWR_SLEEP (1 << 5)
>> +
>> +#define S3C_PHYCLK (0x04)
>> +
>> +#define S3C_PHYCLK_MODE_SERIAL (1 << 6)
>> +#define S3C_PHYCLK_EXT_OSC (1 << 5)
>> +#define S3C_PHYCLK_COMMON_ON_N (1 << 4)
>> +#define S3C_PHYCLK_ID_PULL (1 << 2)
>> +#define S3C_PHYCLK_CLKSEL_MASK (0x3 << 0)
>> +#define S3C_PHYCLK_CLKSEL_SHIFT (0)
>> +#define S3C_PHYCLK_CLKSEL_48M (0x0 << 0)
>> +#define S3C_PHYCLK_CLKSEL_12M (0x2 << 0)
>> +#define S3C_PHYCLK_CLKSEL_24M (0x3 << 0)
>> +
>> +#define S3C_RSTCON (0x08)
>> +
>> +#define S3C_RSTCON_PHYCLK (1 << 2)
>> +#define S3C_RSTCON_HCLK (1 << 1)
>> +#define S3C_RSTCON_PHY (1 << 0)
>> +
>> +#ifndef MHZ
>> +#define MHZ (1000*1000)
>> +#endif
>> +
>> +enum samsung_cpu_type {
>> + TYPE_S3C64XX,
>> + TYPE_EXYNOS4210,
>> +};
>> +
>> +/*
>> + * struct samsung_usbphy - transceiver driver state
>> + * @phy: transceiver structure
>> + * @plat: platform data
>> + * @dev: The parent device supplied to the probe function
>> + * @clk: usb phy clock
>> + * @regs: usb phy register memory base
>> + * @ref_clk_freq: reference clock frequency selection
>> + * @cpu_type: machine identifier
>> + */
>> +struct samsung_usbphy {
>> + struct usb_phy phy;
>> + struct samsung_usbphy_data *plat;
>> + struct device *dev;
>> + struct clk *clk;
>> + void __iomem *regs;
>> + int ref_clk_freq;
>> + int cpu_type;
>> +};
>> +
>> +#define phy_to_sphy(x) container_of((x), struct samsung_usbphy, phy)
>> +
>> +/*
>> + * Returns reference clock frequency selection value
>> + */
>> +static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
>> +{
>> + struct clk *ref_clk;
>> + int refclk_freq = 0;
>> +
>> + ref_clk = clk_get(sphy->dev, "xusbxti");
>> + if (IS_ERR(ref_clk)) {
>> + dev_err(sphy->dev, "Failed to get reference clock\n");
>> + return PTR_ERR(ref_clk);
>> + }
>> +
>> + switch (clk_get_rate(ref_clk)) {
>> + case 12 * MHZ:
>> + refclk_freq |= S3C_PHYCLK_CLKSEL_12M;
>> + break;
>> + case 24 * MHZ:
>> + refclk_freq |= S3C_PHYCLK_CLKSEL_24M;
>> + break;
>> + default:
>> + case 48 * MHZ:
>> + /* default reference clock */
>> + refclk_freq |= S3C_PHYCLK_CLKSEL_48M;
>> + break;
>> + }
>> + clk_put(ref_clk);
>> +
>> + return refclk_freq;
>> +}
>> +
>> +static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
>> +{
>> + void __iomem *regs = sphy->regs;
>> + u32 phypwr;
>> + u32 phyclk;
>> + u32 rstcon;
>> +
>> + /* set clock frequency for PLL */
>> + phyclk = sphy->ref_clk_freq;
>> + phypwr = readl(regs + S3C_PHYPWR);
>> + rstcon = readl(regs + S3C_RSTCON);
>> +
>> + switch (sphy->cpu_type) {
>> + case TYPE_S3C64XX:
>> + phyclk &= ~(S3C_PHYCLK_COMMON_ON_N);
>> + phypwr &= ~S3C_PHYPWR_NORMAL_MASK;
>> + rstcon |= S3C_RSTCON_PHY;
>> + break;
>> + case TYPE_EXYNOS4210:
>> + phypwr &= ~EXYNOS4_PHYPWR_NORMAL_MASK;
>> + rstcon |= S3C_RSTCON_PHY;
>> + default:
>> + break;
>> + }
>> +
>> + writel(phyclk, regs + S3C_PHYCLK);
>> + /* set to normal of PHY0 */
>> + writel(phypwr, regs + S3C_PHYPWR);
>> + /* reset all ports of PHY and Link */
>> + writel(rstcon, regs + S3C_RSTCON);
>> + udelay(10);
>> + rstcon &= ~S3C_RSTCON_PHY;
>> + writel(rstcon, regs + S3C_RSTCON);
>> +}
>> +
>> +static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
>> +{
>> + void __iomem *regs = sphy->regs;
>> + u32 phypwr;
>> +
>> + phypwr = readl(regs + S3C_PHYPWR);
>> +
>> + switch (sphy->cpu_type) {
>> + case TYPE_S3C64XX:
>> + phypwr |= S3C_PHYPWR_NORMAL_MASK;
>> + break;
>> + case TYPE_EXYNOS4210:
>> + phypwr |= EXYNOS4_PHYPWR_NORMAL_MASK;
>> + default:
>> + break;
>> + }
>> +
>> + /* unset to normal of PHY0 */
>> + writel(phypwr, regs + S3C_PHYPWR);
>> +}
>> +
>> +/*
>> + * The function passed to the usb driver for phy initialization
>> + */
>> +static int samsung_usbphy_init(struct usb_phy *phy)
>> +{
>> + struct samsung_usbphy *sphy;
>> + int ret = 0;
>> +
>> + sphy = phy_to_sphy(phy);
>> +
>> + /* Enable the phy clock */
>> + ret = clk_prepare_enable(sphy->clk);
>> + if (ret) {
>> + dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
>> + return ret;
>> + }
>> +
>> + /* Disable phy isolation */
>> + if (sphy->plat && sphy->plat->pmu_isolation)
>> + sphy->plat->pmu_isolation(false);
>> +
>> + /* Initialize usb phy registers */
>> + samsung_usbphy_enable(sphy);
>> +
>> + /* Disable the phy clock */
>> + clk_disable_unprepare(sphy->clk);
>> + return ret;
>> +}
>> +
>> +/*
>> + * The function passed to the usb driver for phy shutdown
>> + */
>> +static void samsung_usbphy_shutdown(struct usb_phy *phy)
>> +{
>> + struct samsung_usbphy *sphy;
>> +
>> + sphy = phy_to_sphy(phy);
>> +
>> + if (clk_prepare_enable(sphy->clk)) {
>> + dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
>> + return;
>> + }
>> +
>> + /* De-initialize usb phy registers */
>> + samsung_usbphy_disable(sphy);
>> +
>> + /* Enable phy isolation */
>> + if (sphy->plat && sphy->plat->pmu_isolation)
>> + sphy->plat->pmu_isolation(true);
>> +
>> + clk_disable_unprepare(sphy->clk);
>> +}
>> +
>> +static const struct of_device_id samsung_usbphy_dt_match[];
>> +
>> +static inline int samsung_usbphy_get_driver_data(struct platform_device *pdev)
>> +{
>> + if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
>> + int data;
>> + const struct of_device_id *match;
>> + match = of_match_node(samsung_usbphy_dt_match,
>> + pdev->dev.of_node);
>> + data = (int) match->data;
>> + return data;
>> + }
>> +
>> + return platform_get_device_id(pdev)->driver_data;
>> +}
>> +
>> +static int __devinit samsung_usbphy_probe(struct platform_device *pdev)
>> +{
>> + struct samsung_usbphy *sphy;
>> + struct samsung_usbphy_data *pdata;
>> + struct device *dev = &pdev->dev;
>> + struct resource *phy_mem;
>> + void __iomem *phy_base;
>> + struct clk *clk;
>> + int ret = 0;
>> +
>> + pdata = pdev->dev.platform_data;
>> + if (!pdata) {
>> + dev_err(&pdev->dev, "%s: no platform data defined\n", __func__);
>> + return -EINVAL;
>> + }
>> +
>> + phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + if (!phy_mem) {
>> + dev_err(dev, "%s: missing mem resource\n", __func__);
>> + return -ENODEV;
>> + }
>> +
>> + phy_base = devm_request_and_ioremap(dev, phy_mem);
>> + if (!phy_base) {
>> + dev_err(dev, "%s: register mapping failed\n", __func__);
>> + return -ENXIO;
>> + }
>> +
>> + sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
>> + if (!sphy)
>> + return -ENOMEM;
>> +
>> + clk = devm_clk_get(dev, "otg");
>> + if (IS_ERR(clk)) {
>> + dev_err(dev, "Failed to get otg clock\n");
>> + return PTR_ERR(clk);
>> + }
>> +
>> + sphy->dev = &pdev->dev;
>> + sphy->plat = pdata;
>> + sphy->regs = phy_base;
>> + sphy->clk = clk;
>> + sphy->phy.dev = sphy->dev;
>> + sphy->phy.label = "samsung-usbphy";
>> + sphy->phy.init = samsung_usbphy_init;
>> + sphy->phy.shutdown = samsung_usbphy_shutdown;
>> + sphy->cpu_type = samsung_usbphy_get_driver_data(pdev);
>> + sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy);
>> +
>> + platform_set_drvdata(pdev, sphy);
>> +
>> + ret = usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
>> + return ret;
>> +}
>> +
>> +static int __exit samsung_usbphy_remove(struct platform_device *pdev)
>> +{
>> + struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
>> +
>> + usb_remove_phy(&sphy->phy);
>> +
>> + return 0;
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +static const struct of_device_id samsung_usbphy_dt_match[] = {
>> + {
>> + .compatible = "samsung,s3c64xx-usbphy",
>> + .data = (void *)TYPE_S3C64XX,
>> + }, {
>> + .compatible = "samsung,exynos4210-usbphy",
>> + .data = (void *)TYPE_EXYNOS4210,
>> + },
>> + {},
>> +};
>> +MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
>> +#else
>> +#define samsung_usbphy_dt_match NULL
>> +#endif
>> +
>> +static struct platform_device_id samsung_usbphy_driver_ids[] = {
>> + {
>> + .name = "s3c64xx-usbphy",
>> + .driver_data = TYPE_S3C64XX,
>> + }, {
>> + .name = "exynos4210-usbphy",
>> + .driver_data = TYPE_EXYNOS4210,
>> + },
>> + {},
>> +};
>> +
>> +MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
>> +
>> +static struct platform_driver samsung_usbphy_driver = {
>> + .probe = samsung_usbphy_probe,
>> + .remove = __devexit_p(samsung_usbphy_remove),
>> + .id_table = samsung_usbphy_driver_ids,
>> + .driver = {
>> + .name = "samsung-usbphy",
>> + .owner = THIS_MODULE,
>> + .of_match_table = samsung_usbphy_dt_match,
>> + },
>> +};
>> +
>> +module_platform_driver(samsung_usbphy_driver);
>> +
>> +MODULE_DESCRIPTION("Samsung USB phy controller");
>> +MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
>> +MODULE_LICENSE("GPL");
>> +MODULE_ALIAS("platform:samsung-usbphy");
>> diff --git a/include/linux/platform_data/samsung-usbphy.h b/include/linux/platform_data/samsung-usbphy.h
>> new file mode 100644
>> index 0000000..1bd24cb
>> --- /dev/null
>> +++ b/include/linux/platform_data/samsung-usbphy.h
>> @@ -0,0 +1,27 @@
>> +/*
>> + * Copyright (C) 2012 Samsung Electronics Co.Ltd
>> + * http://www.samsung.com/
>> + * Author: Praveen Paneri <p.paneri@samsung.com>
>> + *
>> + * Defines platform data for samsung usb phy driver.
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License as published by the
>> + * Free Software Foundation; either version 2 of the License, or (at your
>> + * option) any later version.
>> + */
>> +
>> +#ifndef __SAMSUNG_USBPHY_PLATFORM_H
>> +#define __SAMSUNG_USBPHY_PLATFORM_H
>> +
>> +/**
>> + * samsung_usbphy_data - Platform data for USB PHY driver.
>> + * @pmu_isolation: Function to control usb phy isolation in PMU.
>> + */
>> +struct samsung_usbphy_data {
>> + void (*pmu_isolation)(int on);
>> +};
>> +
>> +extern void samsung_usbphy_set_pdata(struct samsung_usbphy_data *pd);
>> +
>> +#endif /* __SAMSUNG_USBPHY_PLATFORM_H */
>> --
>> 1.7.1
>>
>
> --
> balbi
^ permalink raw reply
* [PATCH 04/10] ASoC: imx: Don't use {en,dis}able_fiq() calls
From: Mark Brown @ 2012-10-16 5:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350337894-9744-4-git-send-email-anton.vorontsov@linaro.org>
On Mon, Oct 15, 2012 at 02:51:28PM -0700, Anton Vorontsov wrote:
> The driver uses platform-specific mxc_set_irq_fiq() with the VIRQ cookie
> passed to it, so it's pretty clear that the driver is absolutely sure
> that the FIQ is routed via platform-specific IC, and that the cookie can
> be used to mask/unmask FIQs. So, let's switch to the genirq routines,
> since we're about to remove FIQ-specific variants.
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
^ permalink raw reply
* [RESEND PATCH v3 2/2] i2c: change id to let i2c-at91 work
From: Bo Shen @ 2012-10-16 5:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350364668-21280-1-git-send-email-voice.shen@atmel.com>
From: voice <voice.shen@atmel.com>
The i2c core driver will turn the platform device ID to busnum
When using platfrom device ID as -1, it means dynamically assigned
the busnum. When writing code, we need to make sure the busnum,
and call i2c_register_board_info(int busnum, ...) to register device
if using -1, we do not know the value of busnum
In order to solve this issue, set the platform device ID as a fix number
Here using 0 to match the busnum used in i2c_regsiter_board_info()
Signed-off-by: Bo Shen <voice.shen@atmel.com>
---
Resend
Cc linux kernel stable mailing list
---
arch/arm/mach-at91/at91rm9200.c | 2 +-
arch/arm/mach-at91/at91rm9200_devices.c | 2 +-
arch/arm/mach-at91/at91sam9260.c | 4 ++--
arch/arm/mach-at91/at91sam9260_devices.c | 2 +-
arch/arm/mach-at91/at91sam9261.c | 4 ++--
arch/arm/mach-at91/at91sam9261_devices.c | 2 +-
arch/arm/mach-at91/at91sam9263.c | 2 +-
arch/arm/mach-at91/at91sam9263_devices.c | 2 +-
arch/arm/mach-at91/at91sam9rl_devices.c | 2 +-
9 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index b4f0565..5269825 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
- CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk),
+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk),
/* fake hclk clock */
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
CLKDEV_CON_ID("pioA", &pioA_clk),
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 7cd8053..1e122bc 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -512,7 +512,7 @@ static struct resource twi_resources[] = {
static struct platform_device at91rm9200_twi_device = {
.name = "i2c-at91rm9200",
- .id = -1,
+ .id = 0,
.resource = twi_resources,
.num_resources = ARRAY_SIZE(twi_resources),
};
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index ad29f93..f820261 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -211,8 +211,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
- CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
- CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk),
+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk),
/* more usart lookup table for DT entries */
CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 44385a4..aa1e587 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -421,7 +421,7 @@ static struct resource twi_resources[] = {
};
static struct platform_device at91sam9260_twi_device = {
- .id = -1,
+ .id = 0,
.resource = twi_resources,
.num_resources = ARRAY_SIZE(twi_resources),
};
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 8d999eb..04295c0 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -178,8 +178,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
- CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk),
- CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk),
+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk),
+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk),
CLKDEV_CON_ID("pioA", &pioA_clk),
CLKDEV_CON_ID("pioB", &pioB_clk),
CLKDEV_CON_ID("pioC", &pioC_clk),
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 0256a00..b948769 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -317,7 +317,7 @@ static struct resource twi_resources[] = {
};
static struct platform_device at91sam9261_twi_device = {
- .id = -1,
+ .id = 0,
.resource = twi_resources,
.num_resources = ARRAY_SIZE(twi_resources),
};
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 6a01d03..d6f9c23 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -193,7 +193,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
- CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
/* fake hclk clock */
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
CLKDEV_CON_ID("pioA", &pioA_clk),
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 23b6384..cb85da2 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -600,7 +600,7 @@ static struct resource twi_resources[] = {
static struct platform_device at91sam9263_twi_device = {
.name = "i2c-at91sam9260",
- .id = -1,
+ .id = 0,
.resource = twi_resources,
.num_resources = ARRAY_SIZE(twi_resources),
};
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 3d2c81d..5047bdc 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -347,7 +347,7 @@ static struct resource twi_resources[] = {
static struct platform_device at91sam9rl_twi_device = {
.name = "i2c-at91sam9g20",
- .id = -1,
+ .id = 0,
.resource = twi_resources,
.num_resources = ARRAY_SIZE(twi_resources),
};
--
1.7.9.5
^ permalink raw reply related
* [RESEND PATCH v3 1/2] i2c: change id to let i2c-gpio work
From: Bo Shen @ 2012-10-16 5:17 UTC (permalink / raw)
To: linux-arm-kernel
From: voice <voice.shen@atmel.com>
The i2c core driver will turn the platform device ID to busnum
When using platfrom device ID as -1, it means dynamically assigned
the busnum. When writing code, we need to make sure the busnum,
and call i2c_register_board_info(int busnum, ...) to register device
if using -1, we do not know the value of busnum
In order to solve this issue, set the platform device ID as a fix number
Here using 0 to match the busnum used in i2c_regsiter_board_info()
Signed-off-by: Bo Shen <voice.shen@atmel.com>
---
Resend
Cc linux kernel stable mailing list
Change since v2
Fix this issue for more boards
Change since v1
Make the commit message more clear
---
arch/arm/mach-at91/at91rm9200_devices.c | 2 +-
arch/arm/mach-at91/at91sam9260_devices.c | 2 +-
arch/arm/mach-at91/at91sam9261_devices.c | 2 +-
arch/arm/mach-at91/at91sam9263_devices.c | 2 +-
arch/arm/mach-at91/at91sam9rl_devices.c | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index a563189..7cd8053 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -479,7 +479,7 @@ static struct i2c_gpio_platform_data pdata = {
static struct platform_device at91rm9200_twi_device = {
.name = "i2c-gpio",
- .id = -1,
+ .id = 0,
.dev.platform_data = &pdata,
};
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index a76b868..44385a4 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -389,7 +389,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,
};
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 9752f17..0256a00 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -285,7 +285,7 @@ static struct i2c_gpio_platform_data pdata = {
static struct platform_device at91sam9261_twi_device = {
.name = "i2c-gpio",
- .id = -1,
+ .id = 0,
.dev.platform_data = &pdata,
};
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 8dde220..23b6384 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -567,7 +567,7 @@ static struct i2c_gpio_platform_data pdata = {
static struct platform_device at91sam9263_twi_device = {
.name = "i2c-gpio",
- .id = -1,
+ .id = 0,
.dev.platform_data = &pdata,
};
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index d6ca054..3d2c81d 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -314,7 +314,7 @@ static struct i2c_gpio_platform_data pdata = {
static struct platform_device at91sam9rl_twi_device = {
.name = "i2c-gpio",
- .id = -1,
+ .id = 0,
.dev.platform_data = &pdata,
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/2] ASoC: Ux500: Dispose of device nodes correctly
From: Mark Brown @ 2012-10-16 5:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350306806-5688-1-git-send-email-lee.jones@linaro.org>
On Mon, Oct 15, 2012 at 02:13:25PM +0100, Lee Jones wrote:
> When of_parse_phandle() is used to find a device node, its
> reference count is incremented by the helper. Once we're
> finished with them, it's our responsibly to ensure they
> are freed in the correct manor.
Applied both, thanks.
^ permalink raw reply
* [PATCH 1/2] regulator: gpio-regulator: Allow use of GPIO controlled regulators though DT
From: Mark Brown @ 2012-10-16 5:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350307020-5910-1-git-send-email-lee.jones@linaro.org>
On Mon, Oct 15, 2012 at 02:16:59PM +0100, Lee Jones wrote:
> Here we provide the GPIO Regulator driver with Device Tree capability, so
> that when a platform is booting with DT instead of platform data we can
> still make full use of it.
Not looked at the patch yet but patch 2 doesn't seem to have appeared?
^ permalink raw reply
* [PATCH 1/2] ASoC: atmel-ssc: use devm_xxx() managed function
From: Mark Brown @ 2012-10-16 5:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350359819-2461-1-git-send-email-voice.shen@atmel.com>
On Tue, Oct 16, 2012 at 11:56:58AM +0800, Bo Shen wrote:
> Using the devm_xxx() managed function to stripdown the error
> and remove code.
Applied both, thanks.
^ permalink raw reply
* [PATCH RESEND] serial/amba-pl011: use devm_* managed resources
From: Domenico Andreoli @ 2012-10-16 4:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350300961-7036-1-git-send-email-linus.walleij@stericsson.com>
On Mon, Oct 15, 2012 at 01:36:01PM +0200, Linus Walleij wrote:
> From: Linus Walleij <linus.walleij@linaro.org>
>
> This switches a bunch of allocation and remapping to use the
> devm_* garbage collected methods and cleans up the error
> path and remove() paths consequently.
>
> devm_ioremap() is only in <linux/io.h> so fix up the
> erroneous <asm/*> include as well.
>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> drivers/tty/serial/amba-pl011.c | 25 +++++++++----------------
> 1 file changed, 9 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
> index d7e1ede..7fca402 100644
> --- a/drivers/tty/serial/amba-pl011.c
> +++ b/drivers/tty/serial/amba-pl011.c
> @@ -56,8 +56,7 @@
> #include <linux/of_device.h>
> #include <linux/pinctrl/consumer.h>
> #include <linux/sizes.h>
> -
> -#include <asm/io.h>
> +#include <linux/io.h>
>
> #define UART_NR 14
>
> @@ -1973,7 +1972,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
> goto out;
> }
>
> - uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
> + uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
> + GFP_KERNEL);
> if (uap == NULL) {
> ret = -ENOMEM;
> goto out;
> @@ -1981,16 +1981,17 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
>
> i = pl011_probe_dt_alias(i, &dev->dev);
>
> - base = ioremap(dev->res.start, resource_size(&dev->res));
> + base = devm_ioremap(&dev->dev, dev->res.start,
> + resource_size(&dev->res));
> if (!base) {
> ret = -ENOMEM;
> - goto free;
> + goto out;
> }
>
> uap->pinctrl = devm_pinctrl_get(&dev->dev);
> if (IS_ERR(uap->pinctrl)) {
> ret = PTR_ERR(uap->pinctrl);
> - goto unmap;
> + goto out;
> }
> uap->pins_default = pinctrl_lookup_state(uap->pinctrl,
> PINCTRL_STATE_DEFAULT);
> @@ -2002,10 +2003,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
> if (IS_ERR(uap->pins_sleep))
> dev_dbg(&dev->dev, "could not get sleep pinstate\n");
>
> - uap->clk = clk_get(&dev->dev, NULL);
> + uap->clk = devm_clk_get(&dev->dev, NULL);
> if (IS_ERR(uap->clk)) {
> ret = PTR_ERR(uap->clk);
> - goto unmap;
> + goto out;
> }
>
> uap->vendor = vendor;
> @@ -2038,11 +2039,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
> amba_set_drvdata(dev, NULL);
> amba_ports[i] = NULL;
> pl011_dma_remove(uap);
> - clk_put(uap->clk);
> - unmap:
> - iounmap(base);
> - free:
> - kfree(uap);
> }
> out:
> return ret;
> @@ -2062,9 +2058,6 @@ static int pl011_remove(struct amba_device *dev)
> amba_ports[i] = NULL;
>
> pl011_dma_remove(uap);
> - iounmap(uap->port.membase);
> - clk_put(uap->clk);
> - kfree(uap);
> return 0;
> }
>
Tested-by: Domenico Andreoli <domenico.andreoli@linux.com>
Thanks,
Domenido
^ permalink raw reply
* ARM: hw_breakpoint: silent EPERM when setting ARM_DSCR_MDBGEN on ARM_DEBUG_ARCH_V7_ECP14
From: Valentin Pistol @ 2012-10-16 4:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAPfQmK+zLLR59FtuxdV82AhcoVV8tNTqGdL2bCh1Nn7YSpLHjg@mail.gmail.com>
> On Fri, Oct 12, 2012 at 7:26 AM, Dietmar Eggemann
> <dietmar.eggemann@arm.com> wrote:
>> I'm running Linaro 12.08 on Pandaboard (Rev A1) and on this board
>> DBGAUTHSTATUS.NSNE and DBGAUTHSTATUS.NSE are set.
>>
>> With additional logs in enable_monitor_mode()
>> [arch/arm/kernel/hw_breakpoint.c]:
>>
>> root at linaro-nano:~# dmesg | grep hw-break
>> [ 0.321380] hw-breakpoint: arch_hw_breakpoint_init cpu0 debug_arch=3
>> [ 0.321441] hw-breakpoint: enable_monitor_mode cpu1 DBGDSCR=03070002
>> [ 0.321441] hw-breakpoint: enable_monitor_mode cpu1
>> DBGAUTHSTATUS=000000af
>> [ 0.321502] hw-breakpoint: enable_monitor_mode cpu0 DBGDSCR=03070002
>> [ 0.321533] hw-breakpoint: enable_monitor_mode cpu0
>> DBGAUTHSTATUS=000000af
>> [ 0.321533] hw-breakpoint: found 5 (+1 reserved) breakpoint and 1
>> watchpoint registers.
>> [ 0.321563] hw-breakpoint: maximum watchpoint size is 4 bytes.
>
> Dietmar,
>
> That looks great! Did you flash the prebuilt images from Linaro 12.08
> and replaced the kernel with those extra debug messages on top of
> kernel at git://android.git.linaro.org/kernel/panda? Or are you using
> Will's branch?
> I am using a newer Pandaboard ES (Rev B1) and hope this is not the problem.
> Could you please provide a few instructions to reproduce your setup?
>
I just tried the kernel over at
git://android.git.linaro.org/kernel/panda and used the same branch in
the prebuilt Linaro 12.08:
linaro-tilt-android-tracking e78449e OMAPFB: Asynchronous vsync notification
I used android_omap4_defconfig but CONFIG_HW_HAVE_BREAKPOINT were not
persistent in the .config so I had to manually add HW_HAVE_BREAKPOINT
to arch/arm/Kconfig under ARCH_OMAP and also add PERF_EVENTS
dependency.
Similar to Dietmar I added additional info to
arch/arm/kernel/hw_breakpoint.c and now I can confirm I see the proper
value of DSCR = 0x3078002 and DBGAUTHSTATUS = 0xaf !
Flashing this 3.2 Kernel works without a problem but I am still
interested in getting Will's branch and 3.7 Kernel working.
I tried the above on Will's branch (copy over the
android_omap4_defconfig and edit Kconfig) but the kernel is still
stuck at trying to boot.
I am wondering if I can use all 4 watchpoints available in OMAP4460.
Normally the kernel just reports 1 watchpoint available due to what I
believe is a lack of information on what watchpoint triggered. Would
it be possible to enable all 4 and have a workaround to determine
which WP triggers?
Valentin
^ permalink raw reply
* [PATCH V3 3/3] ARM: SPEAr13xx: Pass DW DMAC platform data from DT
From: Viresh Kumar @ 2012-10-16 4:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3100e691db3f94c22afd98b609a1568d7e70dfe7.1350360935.git.viresh.kumar@linaro.org>
This patch adds dw_dmac's platform data to DT node. It also creates slave info
node for SPEAr13xx, for the devices which were using dw_dmac.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
V1->V3:
------
- renamed filter function
arch/arm/boot/dts/spear1340.dtsi | 19 ++++++++++
arch/arm/boot/dts/spear13xx.dtsi | 38 ++++++++++++++++++++
arch/arm/mach-spear13xx/include/mach/spear.h | 2 --
arch/arm/mach-spear13xx/spear1310.c | 4 +--
arch/arm/mach-spear13xx/spear1340.c | 27 +++-----------
arch/arm/mach-spear13xx/spear13xx.c | 54 ++--------------------------
6 files changed, 65 insertions(+), 79 deletions(-)
diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
index d71fe2a..8ea3f66 100644
--- a/arch/arm/boot/dts/spear1340.dtsi
+++ b/arch/arm/boot/dts/spear1340.dtsi
@@ -24,6 +24,25 @@
status = "disabled";
};
+ dma at ea800000 {
+ slave_info {
+ uart1_tx {
+ bus_id = "uart1_tx";
+ cfg_hi = <0x6000>; /* 0xC << 11 */
+ cfg_lo = <0>;
+ src_master = <0>;
+ dst_master = <1>;
+ };
+ uart1_tx {
+ bus_id = "uart1_tx";
+ cfg_hi = <0x680>; /* 0xD << 7 */
+ cfg_lo = <0>;
+ src_master = <1>;
+ dst_master = <0>;
+ };
+ };
+ };
+
spi1: spi at 5d400000 {
compatible = "arm,pl022", "arm,primecell";
reg = <0x5d400000 0x1000>;
diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
index f7b84ac..f06bb50 100644
--- a/arch/arm/boot/dts/spear13xx.dtsi
+++ b/arch/arm/boot/dts/spear13xx.dtsi
@@ -91,6 +91,37 @@
reg = <0xea800000 0x1000>;
interrupts = <0 19 0x4>;
status = "disabled";
+
+ nr_channels = <8>;
+ chan_allocation_order = <1>;
+ chan_priority = <1>;
+ block_size = <0xfff>;
+ nr_masters = <2>;
+ data_width = <3 3 0 0>;
+
+ slave_info {
+ ssp0_tx {
+ bus_id = "ssp0_tx";
+ cfg_hi = <0x2000>; /* 0x4 << 11 */
+ cfg_lo = <0>;
+ src_master = <0>;
+ dst_master = <0>;
+ };
+ ssp0_rx {
+ bus_id = "ssp0_rx";
+ cfg_hi = <0x280>; /* 0x5 << 7 */
+ cfg_lo = <0>;
+ src_master = <0>;
+ dst_master = <0>;
+ };
+ cf {
+ bus_id = "cf";
+ cfg_hi = <0>;
+ cfg_lo = <0>;
+ src_master = <0>;
+ dst_master = <0>;
+ };
+ };
};
dma at eb000000 {
@@ -98,6 +129,13 @@
reg = <0xeb000000 0x1000>;
interrupts = <0 59 0x4>;
status = "disabled";
+
+ nr_channels = <8>;
+ chan_allocation_order = <1>;
+ chan_priority = <1>;
+ block_size = <0xfff>;
+ nr_masters = <2>;
+ data_width = <3 3 0 0>;
};
fsmc: flash at b0000000 {
diff --git a/arch/arm/mach-spear13xx/include/mach/spear.h b/arch/arm/mach-spear13xx/include/mach/spear.h
index 07d90ac..71bf5b6 100644
--- a/arch/arm/mach-spear13xx/include/mach/spear.h
+++ b/arch/arm/mach-spear13xx/include/mach/spear.h
@@ -43,8 +43,6 @@
#define VA_L2CC_BASE IOMEM(UL(0xFB000000))
/* others */
-#define DMAC0_BASE UL(0xEA800000)
-#define DMAC1_BASE UL(0xEB000000)
#define MCIF_CF_BASE UL(0xB2800000)
/* Devices present in SPEAr1310 */
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index 9fbbfc5..0e60195 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -36,9 +36,7 @@ static struct pl022_ssp_controller ssp1_plat_data = {
/* Add SPEAr1310 auxdata to pass platform data */
static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv),
- OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
- OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
+ OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, "cf"),
OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
OF_DEV_AUXDATA("arm,pl022", SPEAR1310_SSP1_BASE, NULL, &ssp1_plat_data),
diff --git a/arch/arm/mach-spear13xx/spear1340.c b/arch/arm/mach-spear13xx/spear1340.c
index 081014f..7301f14 100644
--- a/arch/arm/mach-spear13xx/spear1340.c
+++ b/arch/arm/mach-spear13xx/spear1340.c
@@ -20,7 +20,6 @@
#include <linux/of_platform.h>
#include <asm/hardware/gic.h>
#include <asm/mach/arch.h>
-#include <mach/dma.h>
#include <mach/generic.h>
#include <mach/spear.h>
@@ -78,26 +77,10 @@
(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
-static struct dw_dma_slave uart1_dma_param[] = {
- {
- /* Tx */
- .cfg_hi = DWC_CFGH_DST_PER(SPEAR1340_DMA_REQ_UART1_TX),
- .cfg_lo = 0,
- .src_master = DMA_MASTER_MEMORY,
- .dst_master = SPEAR1340_DMA_MASTER_UART1,
- }, {
- /* Rx */
- .cfg_hi = DWC_CFGH_SRC_PER(SPEAR1340_DMA_REQ_UART1_RX),
- .cfg_lo = 0,
- .src_master = SPEAR1340_DMA_MASTER_UART1,
- .dst_master = DMA_MASTER_MEMORY,
- }
-};
-
static struct amba_pl011_data uart1_data = {
- .dma_filter = dw_dma_filter,
- .dma_tx_param = &uart1_dma_param[0],
- .dma_rx_param = &uart1_dma_param[1],
+ .dma_filter = dw_dma_generic_filter,
+ .dma_tx_param = "uart1_tx",
+ .dma_rx_param = "uart1_rx",
};
/* SATA device registration */
@@ -158,9 +141,7 @@ static struct ahci_platform_data sata_pdata = {
/* Add SPEAr1340 auxdata to pass platform data */
static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv),
- OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
- OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
+ OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, "cf"),
OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL,
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 5633d69..0e166fa 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -22,67 +22,19 @@
#include <asm/hardware/gic.h>
#include <asm/mach/map.h>
#include <asm/smp_twd.h>
-#include <mach/dma.h>
#include <mach/generic.h>
#include <mach/spear.h>
-/* common dw_dma filter routine to be used by peripherals */
-bool dw_dma_filter(struct dma_chan *chan, void *slave)
-{
- struct dw_dma_slave *dws = (struct dw_dma_slave *)slave;
-
- if (chan->device->dev == dws->dma_dev) {
- chan->private = slave;
- return true;
- } else {
- return false;
- }
-}
-
/* ssp device registration */
-static struct dw_dma_slave ssp_dma_param[] = {
- {
- /* Tx */
- .cfg_hi = DWC_CFGH_DST_PER(DMA_REQ_SSP0_TX),
- .cfg_lo = 0,
- .src_master = DMA_MASTER_MEMORY,
- .dst_master = DMA_MASTER_SSP0,
- }, {
- /* Rx */
- .cfg_hi = DWC_CFGH_SRC_PER(DMA_REQ_SSP0_RX),
- .cfg_lo = 0,
- .src_master = DMA_MASTER_SSP0,
- .dst_master = DMA_MASTER_MEMORY,
- }
-};
-
struct pl022_ssp_controller pl022_plat_data = {
.bus_id = 0,
.enable_dma = 1,
- .dma_filter = dw_dma_filter,
- .dma_rx_param = &ssp_dma_param[1],
- .dma_tx_param = &ssp_dma_param[0],
+ .dma_filter = dw_dma_generic_filter,
+ .dma_rx_param = "ssp0_rx",
+ .dma_tx_param = "ssp0_tx",
.num_chipselect = 3,
};
-/* CF device registration */
-struct dw_dma_slave cf_dma_priv = {
- .cfg_hi = 0,
- .cfg_lo = 0,
- .src_master = 0,
- .dst_master = 0,
-};
-
-/* dmac device registeration */
-struct dw_dma_platform_data dmac_plat_data = {
- .nr_channels = 8,
- .chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
- .chan_priority = CHAN_PRIORITY_DESCENDING,
- .block_size = 4095U,
- .nr_masters = 2,
- .data_width = { 3, 3, 0, 0 },
-};
-
void __init spear13xx_l2x0_init(void)
{
/*
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related
* [PATCH V3 2/3] dmaengine: dw_dmac: Enhance device tree support
From: Viresh Kumar @ 2012-10-16 4:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3100e691db3f94c22afd98b609a1568d7e70dfe7.1350360935.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>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
V2->V3:
------
- Simplified an equation in filter routine
- renamed variable 'val' as 'tmp' in DT parsing routine
V1->V2:
------
- Optimized filter & DT parsing routine
- Removed unnecessary casts from changes
- renamed filter function
- Fixed function prototype and return value of DT parsing routine for !CONFIG_OF
case
- use of_get_child_count()
Documentation/devicetree/bindings/dma/snps-dma.txt | 44 +++++++
drivers/dma/dw_dmac.c | 134 +++++++++++++++++++++
drivers/dma/dw_dmac_regs.h | 4 +
include/linux/dw_dmac.h | 43 ++++---
4 files changed, 208 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..98f33a7 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -1179,6 +1179,50 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
}
+bool dw_dma_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 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 == dw) && (last_bus_id == param))
+ 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)) {
+ chan->private = &dw->sd[i];
+ last_dw = NULL;
+ last_bus_id = NULL;
+
+ return true;
+ }
+ }
+
+ last_dw = dw;
+ last_bus_id = param;
+ return false;
+}
+EXPORT_SYMBOL(dw_dma_generic_filter);
+
/* --------------------- Cyclic DMA API extensions -------------------- */
/**
@@ -1462,6 +1506,91 @@ 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 tmp, 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", &tmp))
+ pdata->chan_allocation_order = (unsigned char)tmp;
+
+ if (!of_property_read_u32(np, "chan_priority", &tmp))
+ pdata->chan_priority = tmp;
+
+ if (!of_property_read_u32(np, "block_size", &tmp))
+ pdata->block_size = tmp;
+
+ if (!of_property_read_u32(np, "nr_masters", &tmp)) {
+ if (tmp > 4)
+ return NULL;
+
+ pdata->nr_masters = tmp;
+ }
+
+ if (!of_property_read_u32_array(np, "data_width", arr,
+ pdata->nr_masters))
+ for (tmp = 0; tmp < pdata->nr_masters; tmp++)
+ pdata->data_width[tmp] = arr[tmp];
+
+ /* parse slave data */
+ sn = of_find_node_by_name(np, "slave_info");
+ if (!sn)
+ return pdata;
+
+ /* calculate number of slaves */
+ tmp = of_get_child_count(sn);
+ if (!tmp)
+ return NULL;
+
+ sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL);
+ if (!sd)
+ return NULL;
+
+ pdata->sd = sd;
+ pdata->sd_count = tmp;
+
+ for_each_child_of_node(sn, cn) {
+ sd->dma_dev = &pdev->dev;
+ of_property_read_string(cn, "bus_id", &sd->bus_id);
+ of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi);
+ of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo);
+ if (!of_property_read_u32(cn, "src_master", &tmp))
+ sd->src_master = tmp;
+
+ if (!of_property_read_u32(cn, "dst_master", &tmp))
+ sd->dst_master = tmp;
+ sd++;
+ }
+
+ return pdata;
+}
+#else
+static inline struct dw_dma_platform_data *
+dw_dma_parse_dt(struct platform_device *pdev)
+{
+ return NULL;
+}
+#endif
+
static int __devinit dw_probe(struct platform_device *pdev)
{
struct dw_dma_platform_data *pdata;
@@ -1478,6 +1607,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 +1644,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..41766de 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_dma_generic_filter(struct dma_chan *chan, void *param);
#endif /* DW_DMAC_H */
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related
* [PATCH V3 1/3] dmaengine: dw_dmac: Update documentation style comments for dw_dma_platform_data
From: Viresh Kumar @ 2012-10-16 4:19 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>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
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] gpio: clps711x: localise <mach/gpio.h> header
From: Alexander Shiyan @ 2012-10-16 4:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201210152136.27074.arnd@arndb.de>
On Mon, 15 Oct 2012 21:36:26 +0000
Arnd Bergmann <arnd@arndb.de> wrote:
> On Monday 15 October 2012, Alexander Shiyan wrote:
> > OK, but since it will be used only in board code, I reintroduce it
> > in arch/arm/mach-clps711x/common.h. On my opinion is no reason to
> > overload include/linux/*.
>
> Can't the board files just call the gpio functions?
Yes we can. And we will do so.
Macro is a helper and used only to get the desired GPIO-number.
--
Alexander Shiyan <shc_work@mail.ru>
^ permalink raw reply
* [PATCH for 3.7] dtb: fix interrupt assignment for ehci/uhci on wm8505
From: Olof Johansson @ 2012-10-16 4:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350104430.6448.3.camel@gitbox>
On Sat, Oct 13, 2012 at 06:00:30PM +1300, Tony Prisk wrote:
> On Sat, 2012-10-13 at 17:18 +1300, Tony Prisk wrote:
> > EHCI and UHCI devices in wm8505.dtsi should use IRQ 0 & 1
> > respectively - not 43 as used on newer models.
>
> Oops - should have been IRQ 1 & 0 - fixed locally.
> >
> > Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
Applied to fixes with the commit message edited as above.
Thanks,
-Olof
^ permalink raw reply
* [PATCH] ARM: dts: compile Integrator device trees
From: Olof Johansson @ 2012-10-16 4:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350073379-23512-1-git-send-email-linus.walleij@linaro.org>
On Fri, Oct 12, 2012 at 10:22:59PM +0200, Linus Walleij wrote:
> This makes sure that the ARM Integrator device trees get compiled
> during build.
>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Thanks, applied to fixes.
-Olof
^ permalink raw reply
* [PATCH 1/2] ARM: mx27_3ds: Reserve memory for camera usage
From: Fabio Estevam @ 2012-10-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121010075222.GN27665@pengutronix.de>
On Wed, Oct 10, 2012 at 4:52 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Wed, Oct 10, 2012 at 12:29:29AM -0300, Fabio Estevam wrote:
>> From: Fabio Estevam <fabio.estevam@freescale.com>
>>
>> Reserve dedicated memory block for camera usage.
>
> Why not use CMA?
Sorry, not familiar with CMA. Could you please point to some board
file/driver that makes use of it?
Regards,
Fabio Estevam
^ permalink raw reply
* [PATCH 2/2] ASoC: atmel-ssc: use module_platform_driver macro
From: Bo Shen @ 2012-10-16 3:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350359819-2461-1-git-send-email-voice.shen@atmel.com>
This patch removes some code duplication by using module_platform_driver
Signed-off-by: Bo Shen <voice.shen@atmel.com>
---
drivers/misc/atmel-ssc.c | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 23dcb76..ac00f83 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -68,7 +68,7 @@ void ssc_free(struct ssc_device *ssc)
}
EXPORT_SYMBOL(ssc_free);
-static int __init ssc_probe(struct platform_device *pdev)
+static int ssc_probe(struct platform_device *pdev)
{
struct resource *regs;
struct ssc_device *ssc;
@@ -135,24 +135,14 @@ static int __devexit ssc_remove(struct platform_device *pdev)
}
static struct platform_driver ssc_driver = {
- .remove = __devexit_p(ssc_remove),
.driver = {
.name = "ssc",
.owner = THIS_MODULE,
},
+ .probe = ssc_probe,
+ .remove = __devexit_p(ssc_remove),
};
-
-static int __init ssc_init(void)
-{
- return platform_driver_probe(&ssc_driver, ssc_probe);
-}
-module_init(ssc_init);
-
-static void __exit ssc_exit(void)
-{
- platform_driver_unregister(&ssc_driver);
-}
-module_exit(ssc_exit);
+module_platform_driver(ssc_driver);
MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91");
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/2] ASoC: atmel-ssc: use devm_xxx() managed function
From: Bo Shen @ 2012-10-16 3:56 UTC (permalink / raw)
To: linux-arm-kernel
Using the devm_xxx() managed function to stripdown the error
and remove code.
Signed-off-by: Bo Shen <voice.shen@atmel.com>
---
drivers/misc/atmel-ssc.c | 47 +++++++++++++++-------------------------------
1 file changed, 15 insertions(+), 32 deletions(-)
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 5bb1877..23dcb76 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -70,37 +70,33 @@ EXPORT_SYMBOL(ssc_free);
static int __init ssc_probe(struct platform_device *pdev)
{
- int retval = 0;
struct resource *regs;
struct ssc_device *ssc;
- ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL);
+ ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
if (!ssc) {
dev_dbg(&pdev->dev, "out of memory\n");
- retval = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
+ ssc->pdev = pdev;
+
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
dev_dbg(&pdev->dev, "no mmio resource defined\n");
- retval = -ENXIO;
- goto out_free;
+ return -ENXIO;
}
- ssc->clk = clk_get(&pdev->dev, "pclk");
- if (IS_ERR(ssc->clk)) {
- dev_dbg(&pdev->dev, "no pclk clock defined\n");
- retval = -ENXIO;
- goto out_free;
- }
-
- ssc->pdev = pdev;
- ssc->regs = ioremap(regs->start, resource_size(regs));
+ ssc->regs = devm_request_and_ioremap(&pdev->dev, regs);
if (!ssc->regs) {
dev_dbg(&pdev->dev, "ioremap failed\n");
- retval = -EINVAL;
- goto out_clk;
+ return -EINVAL;
+ }
+
+ ssc->clk = devm_clk_get(&pdev->dev, "pclk");
+ if (IS_ERR(ssc->clk)) {
+ dev_dbg(&pdev->dev, "no pclk clock defined\n");
+ return -ENXIO;
}
/* disable all interrupts */
@@ -112,8 +108,7 @@ static int __init ssc_probe(struct platform_device *pdev)
ssc->irq = platform_get_irq(pdev, 0);
if (!ssc->irq) {
dev_dbg(&pdev->dev, "could not get irq\n");
- retval = -ENXIO;
- goto out_unmap;
+ return -ENXIO;
}
spin_lock(&user_lock);
@@ -125,16 +120,7 @@ static int __init ssc_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",
ssc->regs, ssc->irq);
- goto out;
-
-out_unmap:
- iounmap(ssc->regs);
-out_clk:
- clk_put(ssc->clk);
-out_free:
- kfree(ssc);
-out:
- return retval;
+ return 0;
}
static int __devexit ssc_remove(struct platform_device *pdev)
@@ -142,10 +128,7 @@ static int __devexit ssc_remove(struct platform_device *pdev)
struct ssc_device *ssc = platform_get_drvdata(pdev);
spin_lock(&user_lock);
- iounmap(ssc->regs);
- clk_put(ssc->clk);
list_del(&ssc->list);
- kfree(ssc);
spin_unlock(&user_lock);
return 0;
--
1.7.9.5
^ permalink raw reply related
* [PATCH] mfd: ab8500: add devicetree support for fuelgauge
From: Rajanikanth H.V @ 2012-10-16 3:36 UTC (permalink / raw)
To: linux-arm-kernel
From: "Rajanikanth H.V" <rajanikanth.hv@stericsson.com>
- This patch adds device tree support for fuelgauge driver
- optimize bm devices platform_data usage and of_probe(...)
Note: of_probe() routine for battery managed devices is made
common across all bm drivers.
- test status:
- interrupt numbers assigned differs between legacy and FDT mode.
Legacy platform_data Mode:
root at ME:/ cat /proc/interrupts
CPU0 CPU1
483: 0 0 ab8500 ab8500-ponkey-dbf
484: 0 0 ab8500 ab8500-ponkey-dbr
485: 0 0 ab8500 BATT_OVV
494: 0 1 ab8500
495: 0 0 ab8500 ab8500-rtc
501: 0 13 ab8500 NCONV_ACCU
503: 7 22 ab8500 CCEOC
504: 0 1 ab8500 CC_INT_CALIB
505: 0 0 ab8500 LOW_BAT_F
516: 0 34 ab8500 ab8500-gpadc
556: 0 0 ab8500 usb-link-status
FDT Mode:
root at ME:/ cat /proc/interrupts
CPU0 CPU1
6: 0 0 ab8500 ab8500-ponkey-dbf
7: 0 0 ab8500 ab8500-ponkey-dbr
8: 0 0 ab8500 BATT_OVV
162: 0 7 ab8500 ab8500-gpadc
163: 0 1 ab8500
164: 0 0 ab8500 ab8500-rtc
484: 0 0 ab8500 usb-link-status
499: 0 4 ab8500 NCONV_ACCU
500: 0 0 ab8500 LOW_BAT_F
502: 0 1 ab8500 CC_INT_CALIB
503: 0 6 ab8500 CCEOC
Signed-off-by: Rajanikanth H.V <rajanikanth.hv@stericsson.com>
---
Documentation/devicetree/bindings/mfd/ab8500.txt | 7 +-
.../devicetree/bindings/power_supply/ab8500/fg.txt | 52 ++
arch/arm/boot/dts/dbx5x0.dtsi | 12 +-
drivers/mfd/ab8500-core.c | 5 +
drivers/power/Makefile | 2 +-
drivers/power/ab8500_bmdata.c | 520 ++++++++++++++++++++
drivers/power/ab8500_btemp.c | 16 +-
drivers/power/ab8500_charger.c | 16 +-
drivers/power/ab8500_fg.c | 89 ++--
drivers/power/abx500_chargalg.c | 8 +-
include/linux/mfd/abx500.h | 36 +-
11 files changed, 670 insertions(+), 93 deletions(-)
create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
create mode 100644 drivers/power/ab8500_bmdata.c
diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt b/Documentation/devicetree/bindings/mfd/ab8500.txt
index ce83c8d..6ca8d81 100644
--- a/Documentation/devicetree/bindings/mfd/ab8500.txt
+++ b/Documentation/devicetree/bindings/mfd/ab8500.txt
@@ -24,7 +24,12 @@ ab8500-bm : : : Battery Manager
ab8500-btemp : : : Battery Temperature
ab8500-charger : : : Battery Charger
ab8500-codec : : : Audio Codec
-ab8500-fg : : : Fuel Gauge
+ab8500-fg : : vddadc : Fuel Gauge
+ : NCONV_ACCU : : Accumulate N Sample Conversion
+ : BATT_OVV : : Battery Over Voltage
+ : LOW_BAT_F : : LOW threshold battery voltage
+ : CC_INT_CALIB : : Coulomb Counter Internal Calibration
+ : CCEOC : : Coulomb Counter End of Conversion
ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter
SW_CONV_END : :
ab8500-gpio : : : GPIO Controller
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
new file mode 100644
index 0000000..f34644c
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
@@ -0,0 +1,52 @@
+=== AB8500 Fuel Gauge Driver ===
+
+AB8500 is a mixed signal multimedia and power management
+device comprising: power and energy-management-module,
+wall-charger, usb-charger, audio codec, general purpose adc,
+tvout, clock management and sim card interface.
+
+Fuelgauge support is part of energy-management-modules, other
+components of this module are:
+main-charger, usb-combo-charger and battery-temperature-monitoring.
+
+The properties below describes the node for fuelgauge driver.
+
+Required Properties:
+- compatible = "stericsson,ab8500-fg"
+
+dependent node:
+ ab8500_battery: ab8500_battery {
+ };
+ This node will provide information on 'thermistor interface' and
+ 'battery technology type' used.
+
+Properties of this node are:
+thermistor-on-batctrl:
+ A boolean value indicating thermistor interface to battery
+
+ Note:
+ 'btemp' and 'batctrl' are the pins interfaced for battery temperature
+ measurement, 'btemp' signal is used when NTC(negative temperature
+ coefficient) resister is interfaced external to battery whereas
+ 'batctrl' pin is used when NTC resister is internal to battery.
+
+ e.g:
+ ab8500_battery_info: ab8500_bat_type {
+ thermistor-on-batctrl;
+ };
+ indiactes: NTC resister is internal to battery, 'batctrl' is used
+ for thermal measurement.
+
+ The absence of property 'thermal-on-batctrl' indicates
+ NTC resister is external to battery and 'btemp' signal is used
+ for thermal measurement.
+
+battery-type:
+ This shall be the battery manufacturing technology type,
+ allowed types are:
+ "UNKNOWN" "NiMH" "LION" "LIPO" "LiFe" "NiCd" "LiMn"
+ e.g:
+ ab8500_battery_info: ab8500_bat_type {
+ stericsson,battery-type = "LIPO";
+ }
+
diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi
index 748ba7a..68317f5 100644
--- a/arch/arm/boot/dts/dbx5x0.dtsi
+++ b/arch/arm/boot/dts/dbx5x0.dtsi
@@ -352,7 +352,17 @@
vddadc-supply = <&ab8500_ldo_tvout_reg>;
};
- ab8500-usb {
+ ab8500_battery: ab8500_battery {
+ stericsson,battery-type = "LIPO";
+ thermistor-on-batctrl;
+ };
+
+ ab8500_fg {
+ compatible = "stericsson,ab8500-fg";
+ battery = <&ab8500_battery>;
+ };
+
+ ab8500_usb {
compatible = "stericsson,ab8500-usb";
interrupts = < 90 0x4
96 0x4
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 1667c77..abc6261 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -1051,8 +1051,13 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
},
{
.name = "ab8500-fg",
+ .of_compatible = "stericsson,ab8500-fg",
.num_resources = ARRAY_SIZE(ab8500_fg_resources),
.resources = ab8500_fg_resources,
+#ifndef CONFIG_USE_OF
+ .platform_data = &ab8500_bm_data,
+ .pdata_size = sizeof(ab8500_bm_data),
+#endif
},
{
.name = "ab8500-chargalg",
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index ee58afb..2c58d4e 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -34,7 +34,7 @@ obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o
obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o
obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
-obj-$(CONFIG_AB8500_BM) += ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o
+obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o
obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c
new file mode 100644
index 0000000..6cf21f6
--- /dev/null
+++ b/drivers/power/ab8500_bmdata.c
@@ -0,0 +1,520 @@
+#include <linux/export.h>
+#include <linux/power_supply.h>
+#include <linux/of.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500/ab8500-bm.h>
+
+/*
+ * These are the defined batteries that uses a NTC and ID resistor placed
+ * inside of the battery pack.
+ * Note that the res_to_temp table must be strictly sorted by falling resistance
+ * values to work.
+ */
+static struct abx500_res_to_temp temp_tbl_A_thermistor[] = {
+ {-5, 53407},
+ { 0, 48594},
+ { 5, 43804},
+ {10, 39188},
+ {15, 34870},
+ {20, 30933},
+ {25, 27422},
+ {30, 24347},
+ {35, 21694},
+ {40, 19431},
+ {45, 17517},
+ {50, 15908},
+ {55, 14561},
+ {60, 13437},
+ {65, 12500},
+};
+static struct abx500_res_to_temp temp_tbl_B_thermistor[] = {
+ {-5, 165418},
+ { 0, 159024},
+ { 5, 151921},
+ {10, 144300},
+ {15, 136424},
+ {20, 128565},
+ {25, 120978},
+ {30, 113875},
+ {35, 107397},
+ {40, 101629},
+ {45, 96592},
+ {50, 92253},
+ {55, 88569},
+ {60, 85461},
+ {65, 82869},
+};
+static struct abx500_v_to_cap cap_tbl_A_thermistor[] = {
+ {4171, 100},
+ {4114, 95},
+ {4009, 83},
+ {3947, 74},
+ {3907, 67},
+ {3863, 59},
+ {3830, 56},
+ {3813, 53},
+ {3791, 46},
+ {3771, 33},
+ {3754, 25},
+ {3735, 20},
+ {3717, 17},
+ {3681, 13},
+ {3664, 8},
+ {3651, 6},
+ {3635, 5},
+ {3560, 3},
+ {3408, 1},
+ {3247, 0},
+};
+static struct abx500_v_to_cap cap_tbl_B_thermistor[] = {
+ {4161, 100},
+ {4124, 98},
+ {4044, 90},
+ {4003, 85},
+ {3966, 80},
+ {3933, 75},
+ {3888, 67},
+ {3849, 60},
+ {3813, 55},
+ {3787, 47},
+ {3772, 30},
+ {3751, 25},
+ {3718, 20},
+ {3681, 16},
+ {3660, 14},
+ {3589, 10},
+ {3546, 7},
+ {3495, 4},
+ {3404, 2},
+ {3250, 0},
+};
+
+static struct abx500_v_to_cap cap_tbl[] = {
+ {4186, 100},
+ {4163, 99},
+ {4114, 95},
+ {4068, 90},
+ {3990, 80},
+ {3926, 70},
+ {3898, 65},
+ {3866, 60},
+ {3833, 55},
+ {3812, 50},
+ {3787, 40},
+ {3768, 30},
+ {3747, 25},
+ {3730, 20},
+ {3705, 15},
+ {3699, 14},
+ {3684, 12},
+ {3672, 9},
+ {3657, 7},
+ {3638, 6},
+ {3556, 4},
+ {3424, 2},
+ {3317, 1},
+ {3094, 0},
+};
+
+/*
+ * Note that the res_to_temp table must be strictly sorted by falling
+ * resistance values to work.
+ */
+static struct abx500_res_to_temp temp_tbl[] = {
+ {-5, 214834},
+ { 0, 162943},
+ { 5, 124820},
+ {10, 96520},
+ {15, 75306},
+ {20, 59254},
+ {25, 47000},
+ {30, 37566},
+ {35, 30245},
+ {40, 24520},
+ {45, 20010},
+ {50, 16432},
+ {55, 13576},
+ {60, 11280},
+ {65, 9425},
+};
+
+/*
+ * Note that the batres_vs_temp table must be strictly sorted by falling
+ * temperature values to work.
+ */
+struct batres_vs_temp temp_to_batres_tbl_thermistor[] = {
+ { 40, 120},
+ { 30, 135},
+ { 20, 165},
+ { 10, 230},
+ { 00, 325},
+ {-10, 445},
+ {-20, 595},
+};
+
+/*
+ * Note that the batres_vs_temp table must be strictly sorted by falling
+ * temperature values to work.
+ */
+struct batres_vs_temp temp_to_batres_tbl_ext_thermistor[] = {
+ { 60, 300},
+ { 30, 300},
+ { 20, 300},
+ { 10, 300},
+ { 00, 300},
+ {-10, 300},
+ {-20, 300},
+};
+
+/* battery resistance table for LI ION 9100 battery */
+struct batres_vs_temp temp_to_batres_tbl_9100[] = {
+ { 60, 180},
+ { 30, 180},
+ { 20, 180},
+ { 10, 180},
+ { 00, 180},
+ {-10, 180},
+ {-20, 180},
+};
+
+struct abx500_battery_type bat_type_thermistor[] = {
+[BATTERY_UNKNOWN] = {
+ /* First element always represent the UNKNOWN battery */
+ .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
+ .resis_high = 0,
+ .resis_low = 0,
+ .battery_resistance = 300,
+ .charge_full_design = 612,
+ .nominal_voltage = 3700,
+ .termination_vol = 4050,
+ .termination_curr = 200,
+ .recharge_vol = 3990,
+ .normal_cur_lvl = 400,
+ .normal_vol_lvl = 4100,
+ .maint_a_cur_lvl = 400,
+ .maint_a_vol_lvl = 4050,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 400,
+ .maint_b_vol_lvl = 4000,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+ .r_to_t_tbl = temp_tbl,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+ .v_to_cap_tbl = cap_tbl,
+ .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+ .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+{
+ .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+ .resis_high = 53407,
+ .resis_low = 12500,
+ .battery_resistance = 300,
+ .charge_full_design = 900,
+ .nominal_voltage = 3600,
+ .termination_vol = 4150,
+ .termination_curr = 80,
+ .recharge_vol = 4130,
+ .normal_cur_lvl = 700,
+ .normal_vol_lvl = 4200,
+ .maint_a_cur_lvl = 600,
+ .maint_a_vol_lvl = 4150,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 600,
+ .maint_b_vol_lvl = 4100,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A_thermistor),
+ .r_to_t_tbl = temp_tbl_A_thermistor,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A_thermistor),
+ .v_to_cap_tbl = cap_tbl_A_thermistor,
+ .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+ .batres_tbl = temp_to_batres_tbl_thermistor,
+
+},
+{
+ .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+ .resis_high = 165418,
+ .resis_low = 82869,
+ .battery_resistance = 300,
+ .charge_full_design = 900,
+ .nominal_voltage = 3600,
+ .termination_vol = 4150,
+ .termination_curr = 80,
+ .recharge_vol = 4130,
+ .normal_cur_lvl = 700,
+ .normal_vol_lvl = 4200,
+ .maint_a_cur_lvl = 600,
+ .maint_a_vol_lvl = 4150,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 600,
+ .maint_b_vol_lvl = 4100,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B_thermistor),
+ .r_to_t_tbl = temp_tbl_B_thermistor,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B_thermistor),
+ .v_to_cap_tbl = cap_tbl_B_thermistor,
+ .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+ .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+};
+
+struct abx500_battery_type bat_type_ext_thermistor[] = {
+[BATTERY_UNKNOWN] = {
+ /* First element always represent the UNKNOWN battery */
+ .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
+ .resis_high = 0,
+ .resis_low = 0,
+ .battery_resistance = 300,
+ .charge_full_design = 612,
+ .nominal_voltage = 3700,
+ .termination_vol = 4050,
+ .termination_curr = 200,
+ .recharge_vol = 3990,
+ .normal_cur_lvl = 400,
+ .normal_vol_lvl = 4100,
+ .maint_a_cur_lvl = 400,
+ .maint_a_vol_lvl = 4050,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 400,
+ .maint_b_vol_lvl = 4000,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+ .r_to_t_tbl = temp_tbl,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+ .v_to_cap_tbl = cap_tbl,
+ .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+ .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+/*
+ * These are the batteries that doesn't have an internal NTC resistor to measure
+ * its temperature. The temperature in this case is measure with a NTC placed
+ * near the battery but on the PCB.
+ */
+{
+ .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+ .resis_high = 76000,
+ .resis_low = 53000,
+ .battery_resistance = 300,
+ .charge_full_design = 900,
+ .nominal_voltage = 3700,
+ .termination_vol = 4150,
+ .termination_curr = 100,
+ .recharge_vol = 4130,
+ .normal_cur_lvl = 700,
+ .normal_vol_lvl = 4200,
+ .maint_a_cur_lvl = 600,
+ .maint_a_vol_lvl = 4150,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 600,
+ .maint_b_vol_lvl = 4100,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+ .r_to_t_tbl = temp_tbl,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+ .v_to_cap_tbl = cap_tbl,
+ .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+ .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+{
+ .name = POWER_SUPPLY_TECHNOLOGY_LION,
+ .resis_high = 30000,
+ .resis_low = 10000,
+ .battery_resistance = 300,
+ .charge_full_design = 950,
+ .nominal_voltage = 3700,
+ .termination_vol = 4150,
+ .termination_curr = 100,
+ .recharge_vol = 4130,
+ .normal_cur_lvl = 700,
+ .normal_vol_lvl = 4200,
+ .maint_a_cur_lvl = 600,
+ .maint_a_vol_lvl = 4150,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 600,
+ .maint_b_vol_lvl = 4100,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+ .r_to_t_tbl = temp_tbl,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+ .v_to_cap_tbl = cap_tbl,
+ .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+ .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+{
+ .name = POWER_SUPPLY_TECHNOLOGY_LION,
+ .resis_high = 95000,
+ .resis_low = 76001,
+ .battery_resistance = 300,
+ .charge_full_design = 950,
+ .nominal_voltage = 3700,
+ .termination_vol = 4150,
+ .termination_curr = 100,
+ .recharge_vol = 4130,
+ .normal_cur_lvl = 700,
+ .normal_vol_lvl = 4200,
+ .maint_a_cur_lvl = 600,
+ .maint_a_vol_lvl = 4150,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 600,
+ .maint_b_vol_lvl = 4100,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+ .r_to_t_tbl = temp_tbl,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+ .v_to_cap_tbl = cap_tbl,
+ .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+ .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+};
+
+static const struct abx500_bm_capacity_levels cap_levels = {
+ .critical = 2,
+ .low = 10,
+ .normal = 70,
+ .high = 95,
+ .full = 100,
+};
+
+static const struct abx500_fg_parameters fg = {
+ .recovery_sleep_timer = 10,
+ .recovery_total_time = 100,
+ .init_timer = 1,
+ .init_discard_time = 5,
+ .init_total_time = 40,
+ .high_curr_time = 60,
+ .accu_charging = 30,
+ .accu_high_curr = 30,
+ .high_curr_threshold = 50,
+ .lowbat_threshold = 3100,
+ .battok_falling_th_sel0 = 2860,
+ .battok_raising_th_sel1 = 2860,
+ .user_cap_limit = 15,
+ .maint_thres = 97,
+};
+
+static const struct abx500_maxim_parameters maxi_params = {
+ .ena_maxi = true,
+ .chg_curr = 910,
+ .wait_cycles = 10,
+ .charger_curr_step = 100,
+};
+
+static const struct abx500_bm_charger_parameters chg = {
+ .usb_volt_max = 5500,
+ .usb_curr_max = 1500,
+ .ac_volt_max = 7500,
+ .ac_curr_max = 1500,
+};
+
+struct abx500_bm_data ab8500_bm_data = {
+ .temp_under = 3,
+ .temp_low = 8,
+ .temp_high = 43,
+ .temp_over = 48,
+ .main_safety_tmr_h = 4,
+ .temp_interval_chg = 20,
+ .temp_interval_nochg = 120,
+ .usb_safety_tmr_h = 4,
+ .bkup_bat_v = BUP_VCH_SEL_2P6V,
+ .bkup_bat_i = BUP_ICH_SEL_150UA,
+ .no_maintenance = false,
+ .adc_therm = ABx500_ADC_THERM_BATCTRL,
+ .chg_unknown_bat = false,
+ .enable_overshoot = false,
+ .fg_res = 100,
+ .cap_levels = &cap_levels,
+ .bat_type = bat_type_thermistor,
+ .n_btypes = 3,
+ .batt_id = 0,
+ .interval_charging = 5,
+ .interval_not_charging = 120,
+ .temp_hysteresis = 3,
+ .gnd_lift_resistance = 34,
+ .maxi = &maxi_params,
+ .chg_params = &chg,
+ .fg_params = &fg,
+};
+
+int __devinit
+bmdevs_of_probe(struct device *dev,
+ struct device_node *np,
+ struct abx500_bm_data **battery)
+{
+ struct abx500_battery_type *btype;
+ struct device_node *np_bat_supply;
+ struct abx500_bm_data *bat;
+ int i, thermistor;
+ char *bat_tech = "UNKNOWN";
+
+ *battery = devm_kzalloc(dev, sizeof(*bat), GFP_KERNEL);
+ if (!*battery) {
+ dev_err(dev, "%s no mem for plat_data\n", __func__);
+ return -ENOMEM;
+ }
+ *battery = &ab8500_bm_data;
+
+ /* get phandle to 'battery-info' node */
+ np_bat_supply = of_parse_phandle(np, "battery", 0);
+ if (!np_bat_supply) {
+ dev_err(dev, "missing property battery\n");
+ return -EINVAL;
+ }
+ if (of_property_read_bool(np_bat_supply,
+ "thermistor-on-batctrl"))
+ thermistor = NTC_INTERNAL;
+ else
+ thermistor = NTC_EXTERNAL;
+
+ bat = *battery;
+ if (thermistor == NTC_EXTERNAL) {
+ bat->n_btypes = 4;
+ bat->bat_type = bat_type_ext_thermistor;
+ bat->adc_therm = ABx500_ADC_THERM_BATTEMP;
+ }
+ bat_tech = (char *)of_get_property(
+ np_bat_supply, "stericsson,battery-type", NULL);
+ if (!bat_tech) {
+ dev_warn(dev, "missing property battery-name/type\n");
+ strncpy(bat_tech, "UNKNOWN", 7);
+ }
+ of_node_put(np_bat_supply);
+
+ if (strncmp(bat_tech, "LION", 4) == 0) {
+ bat->no_maintenance = true;
+ bat->chg_unknown_bat = true;
+ bat->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600;
+ bat->bat_type[BATTERY_UNKNOWN].termination_vol = 4150;
+ bat->bat_type[BATTERY_UNKNOWN].recharge_vol = 4130;
+ bat->bat_type[BATTERY_UNKNOWN].normal_cur_lvl = 520;
+ bat->bat_type[BATTERY_UNKNOWN].normal_vol_lvl = 4200;
+ }
+ /* select the battery resolution table */
+ for (i = 0; i < bat->n_btypes; ++i) {
+ btype = (bat->bat_type + i);
+ if (thermistor == NTC_EXTERNAL) {
+ btype->batres_tbl =
+ temp_to_batres_tbl_ext_thermistor;
+ } else if (strncmp(bat_tech, "LION", 4) == 0) {
+ btype->batres_tbl =
+ temp_to_batres_tbl_9100;
+ } else {
+ btype->batres_tbl =
+ temp_to_batres_tbl_thermistor;
+ }
+ }
+ return 0;
+}
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index bba3cca..803870e 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -93,7 +93,7 @@ struct ab8500_btemp {
struct ab8500 *parent;
struct ab8500_gpadc *gpadc;
struct ab8500_fg *fg;
- struct abx500_btemp_platform_data *pdata;
+ struct abx500_bmdevs_plat_data *pdata;
struct abx500_bm_data *bat;
struct power_supply btemp_psy;
struct ab8500_btemp_events events;
@@ -962,10 +962,10 @@ static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
{
+ struct abx500_bmdevs_plat_data *plat_data = pdev->dev.platform_data;
+ struct ab8500_btemp *di;
int irq, i, ret = 0;
u8 val;
- struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
- struct ab8500_btemp *di;
if (!plat_data) {
dev_err(&pdev->dev, "No platform data\n");
@@ -982,21 +982,13 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
/* get btemp specific platform data */
- di->pdata = plat_data->btemp;
+ di->pdata = plat_data;
if (!di->pdata) {
dev_err(di->dev, "no btemp platform data supplied\n");
ret = -EINVAL;
goto free_device_info;
}
- /* get battery specific platform data */
- di->bat = plat_data->battery;
- if (!di->bat) {
- dev_err(di->dev, "no battery platform data supplied\n");
- ret = -EINVAL;
- goto free_device_info;
- }
-
/* BTEMP supply */
di->btemp_psy.name = "ab8500_btemp";
di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index d4f0c98..78a730c 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -220,7 +220,7 @@ struct ab8500_charger {
bool autopower;
struct ab8500 *parent;
struct ab8500_gpadc *gpadc;
- struct abx500_charger_platform_data *pdata;
+ struct abx500_bmdevs_plat_data *pdata;
struct abx500_bm_data *bat;
struct ab8500_charger_event_flags flags;
struct ab8500_charger_usb_state usb_state;
@@ -2533,9 +2533,9 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev)
static int __devinit ab8500_charger_probe(struct platform_device *pdev)
{
- int irq, i, charger_status, ret = 0;
- struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
+ struct abx500_bmdevs_plat_data *plat_data = pdev->dev.platform_data;
struct ab8500_charger *di;
+ int irq, i, charger_status, ret = 0;
if (!plat_data) {
dev_err(&pdev->dev, "No platform data\n");
@@ -2555,21 +2555,13 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
spin_lock_init(&di->usb_state.usb_lock);
/* get charger specific platform data */
- di->pdata = plat_data->charger;
+ di->pdata = plat_data;
if (!di->pdata) {
dev_err(di->dev, "no charger platform data supplied\n");
ret = -EINVAL;
goto free_device_info;
}
- /* get battery specific platform data */
- di->bat = plat_data->battery;
- if (!di->bat) {
- dev_err(di->dev, "no battery platform data supplied\n");
- ret = -EINVAL;
- goto free_device_info;
- }
-
di->autopower = false;
/* AC supply */
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index bf02225..ff64dd4 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -22,15 +22,16 @@
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/kobject.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500.h>
#include <linux/slab.h>
-#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/delay.h>
-#include <linux/mfd/abx500/ab8500-gpadc.h>
-#include <linux/mfd/abx500.h>
#include <linux/time.h>
+#include <linux/of.h>
#include <linux/completion.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500/ab8500-bm.h>
+#include <linux/mfd/abx500/ab8500-gpadc.h>
#define MILLI_TO_MICRO 1000
#define FG_LSB_IN_MA 1627
@@ -212,7 +213,6 @@ struct ab8500_fg {
struct ab8500_fg_avg_cap avg_cap;
struct ab8500 *parent;
struct ab8500_gpadc *gpadc;
- struct abx500_fg_platform_data *pdata;
struct abx500_bm_data *bat;
struct power_supply fg_psy;
struct workqueue_struct *fg_wq;
@@ -2416,6 +2416,8 @@ static int __devexit ab8500_fg_remove(struct platform_device *pdev)
int ret = 0;
struct ab8500_fg *di = platform_get_drvdata(pdev);
+ of_node_put(pdev->dev.of_node);
+
list_del(&di->node);
/* Disable coulomb counter */
@@ -2429,7 +2431,6 @@ static int __devexit ab8500_fg_remove(struct platform_device *pdev)
flush_scheduled_work();
power_supply_unregister(&di->fg_psy);
platform_set_drvdata(pdev, NULL);
- kfree(di);
return ret;
}
@@ -2442,21 +2443,44 @@ static struct ab8500_fg_interrupts ab8500_fg_irq[] = {
{"CCEOC", ab8500_fg_cc_data_end_handler},
};
+char *supply_interface[] = {
+ "ab8500_chargalg",
+ "ab8500_usb",
+};
+
static int __devinit ab8500_fg_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
+ struct ab8500_fg *di;
int i, irq;
int ret = 0;
- struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
- struct ab8500_fg *di;
- if (!plat_data) {
- dev_err(&pdev->dev, "No platform data\n");
- return -EINVAL;
+ di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+ if (!di) {
+ dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__);
+ if (np) {
+ ret = -ENOMEM;
+ goto release_node;
+ }
+ }
+ di->bat = (struct abx500_bm_data *)
+ pdev->mfd_cell->platform_data;
+ if (!di->bat) {
+ if (np) {
+ ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to get battery information\n");
+ goto release_node;
+ }
+ } else {
+ dev_err(&pdev->dev, "missing dt node for ab8500_fg\n");
+ ret = -EINVAL;
+ goto release_node;
+ }
+ } else {
+ dev_info(&pdev->dev, "falling back to legacy platform data\n");
}
-
- di = kzalloc(sizeof(*di), GFP_KERNEL);
- if (!di)
- return -ENOMEM;
mutex_init(&di->cc_lock);
@@ -2465,29 +2489,13 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
di->parent = dev_get_drvdata(pdev->dev.parent);
di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- /* get fg specific platform data */
- di->pdata = plat_data->fg;
- if (!di->pdata) {
- dev_err(di->dev, "no fg platform data supplied\n");
- ret = -EINVAL;
- goto free_device_info;
- }
-
- /* get battery specific platform data */
- di->bat = plat_data->battery;
- if (!di->bat) {
- dev_err(di->dev, "no battery platform data supplied\n");
- ret = -EINVAL;
- goto free_device_info;
- }
-
di->fg_psy.name = "ab8500_fg";
di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY;
di->fg_psy.properties = ab8500_fg_props;
di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props);
di->fg_psy.get_property = ab8500_fg_get_property;
- di->fg_psy.supplied_to = di->pdata->supplied_to;
- di->fg_psy.num_supplicants = di->pdata->num_supplicants;
+ di->fg_psy.supplied_to = supply_interface;
+ di->fg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
di->fg_psy.external_power_changed = ab8500_fg_external_power_changed;
di->bat_cap.max_mah_design = MILLI_TO_MICRO *
@@ -2506,7 +2514,8 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq");
if (di->fg_wq == NULL) {
dev_err(di->dev, "failed to create work queue\n");
- goto free_device_info;
+ ret = -ENOMEM;
+ goto release_node;
}
/* Init work for running the fg algorithm instantly */
@@ -2605,12 +2614,17 @@ free_irq:
}
free_inst_curr_wq:
destroy_workqueue(di->fg_wq);
-free_device_info:
- kfree(di);
+release_node:
+ of_node_put(np);
return ret;
}
+static const struct of_device_id ab8500_fg_match[] = {
+ { .compatible = "stericsson,ab8500-fg", },
+ { },
+};
+
static struct platform_driver ab8500_fg_driver = {
.probe = ab8500_fg_probe,
.remove = __devexit_p(ab8500_fg_remove),
@@ -2619,6 +2633,7 @@ static struct platform_driver ab8500_fg_driver = {
.driver = {
.name = "ab8500-fg",
.owner = THIS_MODULE,
+ .of_match_table = ab8500_fg_match,
},
};
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 804b88c..88b5cc1 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -231,7 +231,7 @@ struct abx500_chargalg {
struct abx500_chargalg_charger_info chg_info;
struct abx500_chargalg_battery_data batt_data;
struct abx500_chargalg_suspension_status susp_status;
- struct abx500_chargalg_platform_data *pdata;
+ struct abx500_bmdevs_plat_data *pdata;
struct abx500_bm_data *bat;
struct power_supply chargalg_psy;
struct ux500_charger *ac_chg;
@@ -1802,7 +1802,7 @@ static int __devexit abx500_chargalg_remove(struct platform_device *pdev)
static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
{
- struct abx500_bm_plat_data *plat_data;
+ struct abx500_bmdevs_plat_data *plat_data;
int ret = 0;
struct abx500_chargalg *di =
@@ -1812,10 +1812,8 @@ static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
/* get device struct */
di->dev = &pdev->dev;
-
plat_data = pdev->dev.platform_data;
- di->pdata = plat_data->chargalg;
- di->bat = plat_data->battery;
+ di->pdata = plat_data;
/* chargalg supply */
di->chargalg_psy.name = "abx500_chargalg";
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 1318ca6..bbf3ad6 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -382,39 +382,27 @@ struct abx500_bm_data {
int gnd_lift_resistance;
const struct abx500_maxim_parameters *maxi;
const struct abx500_bm_capacity_levels *cap_levels;
- const struct abx500_battery_type *bat_type;
+ struct abx500_battery_type *bat_type;
const struct abx500_bm_charger_parameters *chg_params;
const struct abx500_fg_parameters *fg_params;
};
-struct abx500_chargalg_platform_data {
- char **supplied_to;
- size_t num_supplicants;
-};
-
-struct abx500_charger_platform_data {
- char **supplied_to;
- size_t num_supplicants;
- bool autopower_cfg;
-};
+extern struct abx500_bm_data ab8500_bm_data;
-struct abx500_btemp_platform_data {
- char **supplied_to;
- size_t num_supplicants;
+struct abx500_bmdevs_plat_data {
+ char **supplied_to;
+ size_t num_supplicants;
+ bool autopower_cfg;
};
-struct abx500_fg_platform_data {
- char **supplied_to;
- size_t num_supplicants;
+enum {
+ NTC_EXTERNAL = 0,
+ NTC_INTERNAL,
};
-struct abx500_bm_plat_data {
- struct abx500_bm_data *battery;
- struct abx500_charger_platform_data *charger;
- struct abx500_btemp_platform_data *btemp;
- struct abx500_fg_platform_data *fg;
- struct abx500_chargalg_platform_data *chargalg;
-};
+int bmdevs_of_probe(struct device *dev,
+ struct device_node *np,
+ struct abx500_bm_data **battery);
int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
u8 value);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
From: Felipe Contreras @ 2012-10-16 3:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CALLhW=6_0Rnp7-gNhCexUVzxam54KhoqAF6e8eiH5yo-wKBxzQ@mail.gmail.com>
Hi,
On Tue, Oct 16, 2012 at 3:29 AM, Omar Ramirez Luna <omar.luna@linaro.org> wrote:
>> After your patch, even if I don't use the camera, or the DSP, the
>> iommu devices will be enabled, and will be consuming energy *all the
>> time*. Which I don't think is what we want.
>
> Wrong, the iommu device will be enabled by pm_runtime_get_sync once
> you decide to attach with iommu_attach_device, if you do not use
> camera or the dsp, you won't turn ON the iommus.
I see, somehow I conflated the two functions.
> On probe this patch does pm_runtime_enable, however this doesn't mean
> the device is turned ON or resumed or kept ON all the time.
In fact it's the other way around; pm_runtime_enable turns off the
power (if it's ON).
>>>>> @@ -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);
>>>>
>>>> This will turn on the device unnecessarily, wasting power, and there's
>>>> no need for that, kfree will take care of that without resuming.
>>>
>>> Left aside the aesthetics of having balanced calls, the device will be
>>> enabled if there was a pending resume to be executed, otherwise it
>>> won't, kfree won't increment the disable_depth counter and I don't
>>> think that freeing the pointer is enough reason to ignore
>>> pm_runtime_disable.
>>
>> You are doing __pm_runtime_disable(dev, true), kfree will do
>> __pm_runtime_disable(dev, false), which is what we want. Both will
>> decrement the disable_depth.
>
> I'm quite confused here, could you please point me to the kfree snip
> that does __pm_runtime_disable(dev, false)?
Sorry, not kfree, but the device removal process:
device_del
device_pm_remove
pm_runtime_remove
__pm_runtime_disable <- HERE
bus_remove_device
device_release_driver
__device_release_driver
.remove => platform_drv_remove
.remove => omap_iommu_remove
Actually, it seems the pm is disabled _before_ omap_iommu_remove is
even called, so it's a no-op.
>> But at least you agree that there's a chance that the device will be waken up.
>
> Of course, if there is a pending resume to be executed, it must honor
> that resume request and then turn off the device before removing the
> iommu, IMHO.
Who will turn off the device afterwards?
>>>> Also, I still think that something like this is needed:
>>> ...
>>>> +static struct clk cam_fck = {
>>>> + .name = "cam_fck",
>>>> + .ops = &clkops_omap2_iclk_dflt,
>>>> + .parent = &l3_ick,
>>>> + .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
>>>
>>> a cam_fck name to enable the ick?
>>
>> Yeap, according to the TRM. Take a look at 12.3 Camera ISP Integration
>> Fig 12-50.
>
> What I meant is that, you are using the CM_ICLKEN to enable a clock
> named "cam_fck" which has l3_ick as a parent. And that is not
> consistent with what that register is meant to do, which is:
>
> 4.14.1.10 CAM_CM Registers
>
> CM_ICKLEN_CAM
> 0x0: CAM_L3_ICK and CAM_L4_ICLK are disabled
> 0x1: CAM_L3_ICK and CAM_L4_ICLK are enabled
>
> So, I'm complaining about the name "cam_fck", for an interface clock
> with parent l3_ick. However I don't know why on section 12.3 they
> refer to CAM_FCK to a l3_ick child clock.
Because it's also used as a functional clock. Anyway, I don't care
much about the name of the clock, what is clear is that there's a link
missing to the l3_ick.
Cheers.
--
Felipe Contreras
^ 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