* [PATCH RESEND 1/5 v6] gpio: Add a block GPIO API to gpiolib
From: Grant Likely @ 2012-10-31 18:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50915DBC.2000802@antcom.de>
Hi Roland
On Wed, Oct 31, 2012 at 6:19 PM, Roland Stigge <stigge@antcom.de> wrote:
> On 10/31/2012 04:00 PM, Grant Likely wrote:
>> For the API, I don't think it is a good idea at all to try and
>> abstract away gpios on multiple controllers. I understand that it
>> makes life a lot easier for userspace to abstract those details away,
>> but the problem is that it hides very important information about how
>> the system is actually constructed that is important to actually get
>> things to work. For example, say you have a gpio-connected device with
>> the constraint that GPIOA must change either before or at the same
>> time as GPIOB, but never after. If those GPIOs are on separate
>> controllers, then the order is completely undefined
>
> It is correct that it's not (yet) well documented and the API is also
> not very explicit about it, but the actual approach of the manipulation
> order is to let drivers handle gpios "as simultaneous as possible" and
> when not possible, do it in the _order of bits specified_ (either
> defined at the device tree level, or when created via
> block_gpio_create() directly).
The documentation is actually fine. I do understand that the intent is
"as simultaneous as possible", but I accept the point that the order
of specification affects the behaviour*. However, it still remains
that the method used by the ABI abstracts at the wrong level and that
blocking arbitrary GPIO pins into a single virtual GPIO register is a
bad idea.
*note that the current code doesn't implement that intended behaviour
either since the gpios are processed in the order of the controllers,
not the order of the bits.
> I'm not sure how far you tested the API in depth: You can already define
> a block that maps onto a subset of gpios on a controller and internally
> of course maps onto those set and clear operations. Whenever you need to
> manipulate a different subset (whether disjoint or overlapping), you can
> easily define _additional_ blocks. From my experience, this solves most
> of the real world problems when n-bit busses are bit banged over GPIOs.
> Doesn't this already solve this (in a different way, though)?
Blech! Requiring a new block for each possible combination of
write-at-once bits is a horrible ABI. That just strengthens my opinion
that the abstraction isn't right yet.
> Pin direction currently needs to be set up separately, analogous to
> requesting gpios. Need to document this better, right. The assumption is
> that I/O needs to be efficient primarily, before bloating the API with
> direction functions. Or should I add functions for this?
Since this is a userspace facing ABI, once it is merged it cannot be
changed in an incompatible way. I cannot merge it until there is at
least a plan for how to handle all of the reasonable use cases. That
means it must support set/clear or mask operations. Also, if it sticks
with the design of grouping pins from multiple controllers, then it
needs to handle explicitly constraining what order operations are
performed in at the time of the operation. At the time of setup
doesn't work since constraints between pins may not always be in the
same order.
I really think you should consider implementing a command stream type
of interface.
g.
^ permalink raw reply
* [PATCH v4 1/2] ARM: clk-imx27: Add missing clock for mx2-camera
From: Sascha Hauer @ 2012-10-31 19:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121031165303.32921a5c@infradead.org>
On Wed, Oct 31, 2012 at 04:53:03PM -0200, Mauro Carvalho Chehab wrote:
> Em Wed, 31 Oct 2012 14:53:47 +0100 (CET)
> Guennadi Liakhovetski <g.liakhovetski@gmx.de> escreveu:
>
> > On Wed, 31 Oct 2012, Fabio Estevam wrote:
> >
> > > Hi Sascha,
> > >
> > > On Wed, Oct 31, 2012 at 11:16 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > >
> > > > Quoting yourself:
> > > >
> > > >> Forgot to comment: as patch 2 relies on this change, the better, IMHO, is
> > > >> to send both via the same tree. If you decide to do so, please get arm
> > > >> maintainer's ack, instead, and we can merge both via my tree.
> > > >
> > > > That's why Fabio resent these patches with my Ack. You are free to take
> > > > these.
> > >
> > > I have just realized that this patch (1/2) will not apply against
> > > media tree because it does not have commit 27b76486a3 (media:
> > > mx2_camera: remove cpu_is_xxx by using platform_device_id), which
> > > changes from mx2_camera.0 to imx27-camera.0.
> >
> > This is exactly the reason why I wasn't able to merge it. The problem was,
> > that this "media: mx2_camera: remove cpu_is_xxx by using
> > platform_device_id" patch non-trivially touched both arch/arm/ and
> > drivers/media/ directories. And being patch 27/34 I didn't feel like
> > asking the author to redo it again:-) This confirms, that it's better to
> > avoid such overlapping patches whenever possible.
> >
> > > So it seems to be better to merge this via arm tree to avoid such conflict.
>
> I agree with Fabio and Guennadi. There are so many changes happening at arm
> that merging those two patches there will likely be easier for everybody.
Ok, then I'll take them. I wasn't aware in arm-soc are sitting patches
for this driver already.
>
> Otherwise, I'll need to pull from some arm tree that never rebase, with
> the needed patches, and coordinate with you during the merge window,
> to be sure that patches will arrive there at the right order, from the
> right tree.
Hopefully these kind of cross dependencies become fewer over time. SoC
code is getting smaller and gets better abstracted from the drivers, so
chances are good.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH V4 0/4] ARM: tegra: Enable SLINK controller driver
From: Stephen Warren @ 2012-10-31 19:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5091607D.8010907@nvidia.com>
On 10/31/2012 11:31 AM, Laxman Dewangan wrote:
> On Wednesday 31 October 2012 09:59 PM, Stephen Warren wrote:
>> On 10/31/2012 03:02 AM, Laxman Dewangan wrote:
>>> This series modify the dts file to add the slink addresses,
>>> make AUXDATA in board dt files, enable slink4 for tegra30-cardhu and
>>> enable slink controller defconfig.
>> I don't appear to have received patch 1/4 this time around. I'll assume
>> it's identical to V3, since I don't think anything needed to change
>> there...
>
> Yes, it is identical to V3, no change on the 1/4.
OK, I have applied the series now. Thanks.
BTW, I noticed that the Cardu board files sets the SPI controller's max
frequency to 25MHZ (which is consistent with the commit description) but
the SPI flash node's frequency to 20MHz. Was that intended, or should I
fix it up to be 25MHz?
> Only change in 3/4 and 4/4. I realize later that you already applied the
> 2/4 yesterday.
Oops, that was a mistake; I forgot to pull it out after testing and not
getting it to work. Oh well.
^ permalink raw reply
* [GIT PULL] Calxeda ECX-2000 support
From: Rob Herring @ 2012-10-31 19:17 UTC (permalink / raw)
To: linux-arm-kernel
Arnd, Olof,
Please pull support for Calxeda ECX-2000 SOC.
There will be a trivial conflict with the GIC move to drivers/irqchip once
that goes in.
Rob
The following changes since commit 8f0d8163b50e01f398b14bcd4dc039ac5ab18d64:
Linux 3.7-rc3 (2012-10-28 12:24:48 -0700)
are available in the git repository at:
git://sources.calxeda.com/kernel/linux.git tags/calxeda-ecx-2000
for you to fetch changes up to e095c0d122c09efabe7d4136ce77f72c636c4879:
ARM: highbank: Add initial ECX-2000 support (2012-10-31 13:47:01 -0500)
----------------------------------------------------------------
Support for Calxeda ECX-2000 SOC
----------------------------------------------------------------
Rob Herring (6):
ARM: highbank: disable unused sdhci and gpio in dts
ARM: highbank: enable coherent DMA for xgmac in dts
ARM: dts: Add Calxeda ECX-2000 support
ARM: smp_twd: don't warn on no DT node
ARM: highbank: abstract out SCU usage
ARM: highbank: Add initial ECX-2000 support
Documentation/devicetree/bindings/arm/calxeda.txt | 13 +-
arch/arm/boot/dts/Makefile | 3 +-
arch/arm/boot/dts/ecx-2000.dts | 104 +++++++++
arch/arm/boot/dts/ecx-common.dtsi | 237 +++++++++++++++++++++
arch/arm/boot/dts/highbank.dts | 212 +-----------------
arch/arm/kernel/smp_twd.c | 6 +-
arch/arm/mach-highbank/Kconfig | 2 +-
arch/arm/mach-highbank/highbank.c | 27 +--
arch/arm/mach-highbank/hotplug.c | 6 +-
arch/arm/mach-highbank/platsmp.c | 7 +-
arch/arm/mach-highbank/pm.c | 3 -
arch/arm/mach-highbank/sysregs.h | 19 ++
arch/arm/mach-highbank/system.c | 2 -
13 files changed, 394 insertions(+), 247 deletions(-)
create mode 100644 arch/arm/boot/dts/ecx-2000.dts
create mode 100644 arch/arm/boot/dts/ecx-common.dtsi
^ permalink raw reply
* [PATCH 7/8] serial: xilinx_uartps: get clock rate info from dts
From: Josh Cartwright @ 2012-10-31 19:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1351721190.git.josh.cartwright@ni.com>
Add support for specifying clock information for the uart clk via the
device tree. This eliminates the need to hardcode rates in the device
tree.
Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
---
arch/arm/boot/dts/zynq-7000.dtsi | 4 ++--
drivers/tty/serial/xilinx_uartps.c | 30 +++++++++++++++++-------------
2 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index bb3085c..5fb763f 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -44,14 +44,14 @@
compatible = "xlnx,xuartps";
reg = <0xE0000000 0x1000>;
interrupts = <0 27 4>;
- clock = <50000000>;
+ clocks = <&uart_clk 0>;
};
uart1: uart at e0001000 {
compatible = "xlnx,xuartps";
reg = <0xE0001000 0x1000>;
interrupts = <0 50 4>;
- clock = <50000000>;
+ clocks = <&uart_clk 0>;
};
slcr: slcr at f8000000 {
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index 23efe17..adfecbc 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -17,6 +17,7 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/console.h>
+#include <linux/clk.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -944,18 +945,20 @@ static int __devinit xuartps_probe(struct platform_device *pdev)
int rc;
struct uart_port *port;
struct resource *res, *res2;
- int clk = 0;
+ struct clk *clk;
- const unsigned int *prop;
-
- prop = of_get_property(pdev->dev.of_node, "clock", NULL);
- if (prop)
- clk = be32_to_cpup(prop);
+ clk = of_clk_get(pdev->dev.of_node, 0);
if (!clk) {
dev_err(&pdev->dev, "no clock specified\n");
return -ENODEV;
}
+ rc = clk_prepare_enable(clk);
+ if (rc) {
+ dev_err(&pdev->dev, "could not enable clock\n");
+ return -EBUSY;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
@@ -978,7 +981,8 @@ static int __devinit xuartps_probe(struct platform_device *pdev)
port->mapbase = res->start;
port->irq = res2->start;
port->dev = &pdev->dev;
- port->uartclk = clk;
+ port->uartclk = clk_get_rate(clk);
+ port->private_data = clk;
dev_set_drvdata(&pdev->dev, port);
rc = uart_add_one_port(&xuartps_uart_driver, port);
if (rc) {
@@ -1000,14 +1004,14 @@ static int __devinit xuartps_probe(struct platform_device *pdev)
static int __devexit xuartps_remove(struct platform_device *pdev)
{
struct uart_port *port = dev_get_drvdata(&pdev->dev);
- int rc = 0;
+ struct clk *clk = port->private_data;
+ int rc;
/* Remove the xuartps port from the serial core */
- if (port) {
- rc = uart_remove_one_port(&xuartps_uart_driver, port);
- dev_set_drvdata(&pdev->dev, NULL);
- port->mapbase = 0;
- }
+ rc = uart_remove_one_port(&xuartps_uart_driver, port);
+ dev_set_drvdata(&pdev->dev, NULL);
+ port->mapbase = 0;
+ clk_disable_unprepare(clk);
return rc;
}
--
1.8.0
^ permalink raw reply related
* [PATCH v2 4/5] serial: xilinx_uartps: get clock rate info from dts
From: Josh Cartwright @ 2012-10-31 19:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1352400580.git.josh.cartwright@ni.com>
Add support for specifying clock information for the uart clk via the
device tree. This eliminates the need to hardcode rates in the device
tree.
Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
---
arch/arm/boot/dts/zynq-7000.dtsi | 4 ++--
drivers/tty/serial/xilinx_uartps.c | 30 +++++++++++++++++-------------
2 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index bb3085c..c975c2d 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -44,14 +44,14 @@
compatible = "xlnx,xuartps";
reg = <0xE0000000 0x1000>;
interrupts = <0 27 4>;
- clock = <50000000>;
+ clocks = <&uart_clk 0>;
};
uart1: uart at e0001000 {
compatible = "xlnx,xuartps";
reg = <0xE0001000 0x1000>;
interrupts = <0 50 4>;
- clock = <50000000>;
+ clocks = <&uart_clk 1>;
};
slcr: slcr at f8000000 {
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index 23efe17..adfecbc 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -17,6 +17,7 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/console.h>
+#include <linux/clk.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -944,18 +945,20 @@ static int __devinit xuartps_probe(struct platform_device *pdev)
int rc;
struct uart_port *port;
struct resource *res, *res2;
- int clk = 0;
+ struct clk *clk;
- const unsigned int *prop;
-
- prop = of_get_property(pdev->dev.of_node, "clock", NULL);
- if (prop)
- clk = be32_to_cpup(prop);
+ clk = of_clk_get(pdev->dev.of_node, 0);
if (!clk) {
dev_err(&pdev->dev, "no clock specified\n");
return -ENODEV;
}
+ rc = clk_prepare_enable(clk);
+ if (rc) {
+ dev_err(&pdev->dev, "could not enable clock\n");
+ return -EBUSY;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
@@ -978,7 +981,8 @@ static int __devinit xuartps_probe(struct platform_device *pdev)
port->mapbase = res->start;
port->irq = res2->start;
port->dev = &pdev->dev;
- port->uartclk = clk;
+ port->uartclk = clk_get_rate(clk);
+ port->private_data = clk;
dev_set_drvdata(&pdev->dev, port);
rc = uart_add_one_port(&xuartps_uart_driver, port);
if (rc) {
@@ -1000,14 +1004,14 @@ static int __devinit xuartps_probe(struct platform_device *pdev)
static int __devexit xuartps_remove(struct platform_device *pdev)
{
struct uart_port *port = dev_get_drvdata(&pdev->dev);
- int rc = 0;
+ struct clk *clk = port->private_data;
+ int rc;
/* Remove the xuartps port from the serial core */
- if (port) {
- rc = uart_remove_one_port(&xuartps_uart_driver, port);
- dev_set_drvdata(&pdev->dev, NULL);
- port->mapbase = 0;
- }
+ rc = uart_remove_one_port(&xuartps_uart_driver, port);
+ dev_set_drvdata(&pdev->dev, NULL);
+ port->mapbase = 0;
+ clk_disable_unprepare(clk);
return rc;
}
--
1.8.0
^ permalink raw reply related
* [PATCH RESEND 1/5 v6] gpio: Add a block GPIO API to gpiolib
From: Mark Brown @ 2012-10-31 19:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACxGe6vgryMPygc8SKFLKqP8Wq=pcGiJe_dPCiDC-evzf32UMA@mail.gmail.com>
On Wed, Oct 31, 2012 at 04:00:17PM +0100, Grant Likely wrote:
> For the API, I don't think it is a good idea at all to try and
> abstract away gpios on multiple controllers. I understand that it
> makes life a lot easier for userspace to abstract those details away,
> but the problem is that it hides very important information about how
> the system is actually constructed that is important to actually get
> things to work. For example, say you have a gpio-connected device with
> the constraint that GPIOA must change either before or at the same
> time as GPIOB, but never after. If those GPIOs are on separate
> controllers, then the order is completely undefined, and the user has
> no way to control that other than to fall back to manipulating GPIOs
> one at a time again (and losing all the performance benefits). Either
> controller affinity needs to be explicit in the API, or the API needs
> to be constraint oriented (ie. a stream of commands and individual
> commands can be coalesced if they meet the constraints**). Also, the
> API requires remapping the GPIO numbers which forces the code to be a
> lot more complex than it needs to be.
It feels like I'm missing something here but can we not simply say that
if the user cares about the ordering of the signal changes within an
update then they should be doing two separate updates? Most of the
cases I'm aware of do things as an update with a strobe or clock that
latches the values.
The big advantage of grouping things together is that it means that we
centralise the fallback code.
> I would rather see new attribute(s) added to the gpiochip's directory
> to allow modifying all the pins on a given controller. It's
> considerably less complex, and I'm a lot happier about extending the
> sysfs ABI in that way than committing to the remapping block approach.
When I've looked at this stuff I've only looked at and thought about in
kernel users. The gpiolib sysfs ABI is already fun enough :)
^ permalink raw reply
* [PATCH 3/8] ARM: zynq: dts: add description of the second uart
From: Josh Cartwright @ 2012-10-31 19:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1351721190.git.josh.cartwright@ni.com>
The zynq-7000 has an additional UART at 0xE0001000. Describe it in the
device tree.
Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
---
arch/arm/boot/dts/zynq-ep107.dts | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-ep107.dts
index 574bc04..5caf100 100644
--- a/arch/arm/boot/dts/zynq-ep107.dts
+++ b/arch/arm/boot/dts/zynq-ep107.dts
@@ -59,5 +59,12 @@
interrupts = <0 27 4>;
clock = <50000000>;
};
+
+ uart1: uart at e0001000 {
+ compatible = "xlnx,xuartps";
+ reg = <0xE0001000 0x1000>;
+ interrupts = <0 50 4>;
+ clock = <50000000>;
+ };
};
};
--
1.8.0
^ permalink raw reply related
* [PATCH v4 1/2] ARM: clk-imx27: Add missing clock for mx2-camera
From: Mauro Carvalho Chehab @ 2012-10-31 19:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121031190249.GO1641@pengutronix.de>
Em Wed, 31 Oct 2012 20:02:49 +0100
Sascha Hauer <s.hauer@pengutronix.de> escreveu:
> On Wed, Oct 31, 2012 at 04:53:03PM -0200, Mauro Carvalho Chehab wrote:
> > Em Wed, 31 Oct 2012 14:53:47 +0100 (CET)
> > Guennadi Liakhovetski <g.liakhovetski@gmx.de> escreveu:
> >
> > > On Wed, 31 Oct 2012, Fabio Estevam wrote:
> > I agree with Fabio and Guennadi. There are so many changes happening at arm
> > that merging those two patches there will likely be easier for everybody.
>
> Ok, then I'll take them. I wasn't aware in arm-soc are sitting patches
> for this driver already.
Thank you!
> >
> > Otherwise, I'll need to pull from some arm tree that never rebase, with
> > the needed patches, and coordinate with you during the merge window,
> > to be sure that patches will arrive there at the right order, from the
> > right tree.
>
> Hopefully these kind of cross dependencies become fewer over time. SoC
> code is getting smaller and gets better abstracted from the drivers, so
> chances are good.
Yes, I'm expecting so.
Regards,
Mauro
^ permalink raw reply
* [PATCH V3] mmc: omap_hsmmc: Enable HSPE bit for high speed cards
From: Venkatraman S @ 2012-10-31 19:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121031122639.GA10998@arwen.pp.htv.fi>
On Wed, Oct 31, 2012 at 5:56 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Wed, Oct 31, 2012 at 05:27:36PM +0530, Hebbar, Gururaja wrote:
>> HSMMC IP on AM33xx need a special setting to handle High-speed cards.
>> Other platforms like TI81xx, OMAP4 may need this as-well. This depends
>> on the HSMMC IP timing closure done for the high speed cards.
>>
>> From AM335x TRM (SPRUH73F - 18.3.12 Output Signals Generation)
>>
>> The MMC/SD/SDIO output signals can be driven on either falling edge or
>> rising edge depending on the SD_HCTL[2] HSPE bit. This feature allows
>> to reach better timing performance, and thus to increase data transfer
>> frequency.
>>
>> There are few pre-requisites for enabling the HSPE bit
>> - Controller should support High-Speed-Enable Bit and
>> - Controller should not be using DDR Mode and
>> - Controller should advertise that it supports High Speed in
>> capabilities register and
>> - MMC/SD clock coming out of controller > 25MHz
>>
>> Note:
>> The implementation reuses the output of calc_divisor() so as to reduce
>> code addition.
>>
>> Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>
>
> this looks good to my eyes, hopefully I haven't missed anything:
>
> Reviewed-by: Felipe Balbi <balbi@ti.com>
>
Except for the excessively verbose comments which are just duplicating the code,
<Quote>
>> + * Enable High-Speed Support
>> + * Pre-Requisites
>> + * - Controller should support High-Speed-Enable Bit
>> + * - Controller should not be using DDR Mode
>> + * - Controller should advertise that it supports High Speed
>> + * in capabilities register
>> + * - MMC/SD clock coming out of controller > 25MHz
>> + */
</Quote>
I'm ok with this patch as well. I'm putting a few patches under test
including this one,
and will send it to Chris as part of that series.
I'll strip out the above mentioned comments, unless there are any objections.
Thanks,
Venkat.
^ permalink raw reply
* [PATCH 4/4] arm/dts: am33xx: Add CPSW and MDIO module nodes for AM33XX
From: Hiremath, Vaibhav @ 2012-10-31 19:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50914107.2090909@ti.com>
On Wed, Oct 31, 2012 at 20:47:27, Cousson, Benoit wrote:
> Hi,
>
> On 10/29/2012 09:21 AM, Vaibhav Hiremath wrote:
> > From: Mugunthan V N <mugunthanvnm@ti.com>
> >
> > Add CPSW and MDIO related device tree data for AM33XX.
> > Also enable them into board/evm dts files by providing
> > respective phy-id.
>
> Is there any bindings documentation for that device?
>
Yes, the base DT binding documentation is present in file
Documentation/devicetree/bindings/net/cpsw.txt
> > Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
> > Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
> > Cc: Richard Cochran <richardcochran@gmail.com>
> > Cc: Benoit Cousson <b-cousson@ti.com>
> > ---
> > arch/arm/boot/dts/am335x-bone.dts | 8 ++++++
> > arch/arm/boot/dts/am335x-evm.dts | 8 ++++++
> > arch/arm/boot/dts/am33xx.dtsi | 50 +++++++++++++++++++++++++++++++++++++
> > 3 files changed, 66 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
> > index c634f87..e233cfa 100644
> > --- a/arch/arm/boot/dts/am335x-bone.dts
> > +++ b/arch/arm/boot/dts/am335x-bone.dts
> > @@ -78,3 +78,11 @@
> > };
> > };
> > };
> > +
> > +&cpsw_emac0 {
> > + phy_id = "4a101000.mdio:00";
>
> Why are you using that kind of interface? You seem to want a reference
> to a device.
>
> Cannot you have something less hard coded like:
> phy_id = <&davinci_mdio>, <0>;
>
>
> > +};
> > +
> > +&cpsw_emac1 {
> > + phy_id = "4a101000.mdio:01";
> > +};
> > diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
> > index 185d632..415c3b3 100644
> > --- a/arch/arm/boot/dts/am335x-evm.dts
> > +++ b/arch/arm/boot/dts/am335x-evm.dts
> > @@ -118,3 +118,11 @@
> > };
> > };
> > };
> > +
> > +&cpsw_emac0 {
> > + phy_id = "4a101000.mdio:00";
> > +};
> > +
> > +&cpsw_emac1 {
> > + phy_id = "4a101000.mdio:01";
> > +};
> > diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
> > index bb31bff..f6bea04 100644
> > --- a/arch/arm/boot/dts/am33xx.dtsi
> > +++ b/arch/arm/boot/dts/am33xx.dtsi
> > @@ -210,5 +210,55 @@
> > interrupt-parent = <&intc>;
> > interrupts = <91>;
> > };
> > +
> > + mac: ethernet at 4A100000 {
>
> hexa data should be in lower case.
>
Oops. Will correct it.
> > + compatible = "ti,cpsw";
> > + ti,hwmods = "cpgmac0";
> > + cpdma_channels = <8>;
> > + host_port_no = <0>;
> > + cpdma_reg_ofs = <0x800>;
> > + cpdma_sram_ofs = <0xa00>;
> > + ale_reg_ofs = <0xd00>;
> > + ale_entries = <1024>;
> > + host_port_reg_ofs = <0x108>;
> > + hw_stats_reg_ofs = <0x900>;
> > + bd_ram_ofs = <0x2000>;
> > + bd_ram_size = <0x2000>;
> > + no_bd_ram = <0>;
> > + rx_descs = <64>;
> > + mac_control = <0x20>;
>
> Do you have to store all these data in the DTS? Cannot it be in the driver?
>
> Do you expect to have several instance of the same IP with different
> parameters here?
>
I will let Mugunthan respond to this.
> > + slaves = <2>;
> > + reg = <0x4a100000 0x800
> > + 0x4a101200 0x100
> > + 0x4a101000 0x100>;
>
> Please align the address.
Ok.
>
> > + #address-cells = <1>;
> > + #size-cells = <1>;
> > + interrupt-parent = <&intc>;
> > + /* c0_rx_thresh_pend c0_rx_pend c0_tx_pend c0_misc_pend*/
>
> Please use a standard multi-line comment instead of trying to put
> everything in one line.
>
Oops. Will correct it.
> > + interrupts = <40 41 42 43>;
> > + ranges;
>
> You should add blank line here for readability.
>
OK.
> > + cpsw_emac0: slave at 0 {
>
> Mmm, you are using some address later and here some relative number,
> that does not looks very consistent.
>
> > + slave_reg_ofs = <0x208>;
>
> Is it an offset from 4a100000? Cannot you use the address for the slave
> name?
>
> Something like that: cpsw_emac0: slave at 4a100208
>
> > + sliver_reg_ofs = <0xd80>;
> > + /* Filled in by U-Boot */
> > + mac-address = [ 00 00 00 00 00 00 ];
> > + };
>
> You should add blank line here for readability.
>
Ok
Thanks,
Vaibhav
^ permalink raw reply
* [PATCH 8/8] clocksource: xilinx_ttc: add OF_CLK support
From: Josh Cartwright @ 2012-10-31 19:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1351721190.git.josh.cartwright@ni.com>
Add support for retrieving TTC configuration from device tree. This
includes the ability to pull information about the driving clocks from
the of_clk bindings.
Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
---
arch/arm/boot/dts/zynq-7000.dtsi | 53 ++++++++
arch/arm/boot/dts/zynq-zc702.dts | 10 ++
drivers/clocksource/xilinx_ttc.c | 273 ++++++++++++++++++++++-----------------
3 files changed, 218 insertions(+), 118 deletions(-)
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index 5fb763f..9a2442c 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -109,5 +109,58 @@
};
};
};
+
+ ttc0: ttc0 at f8001000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "xlnx,ttc";
+ reg = <0xF8001000 0x1000>;
+ clocks = <&cpu_clk 3>;
+ clock-names = "cpu_1x";
+ clock-ranges;
+
+ ttc0_0: ttc0.0 {
+ status = "disabled";
+ reg = <0>;
+ interrupts = <0 10 4>;
+ };
+ ttc0_1: ttc0.1 {
+ status = "disabled";
+ reg = <1>;
+ interrupts = <0 11 4>;
+ };
+ ttc0_2: ttc0.2 {
+ status = "disabled";
+ reg = <2>;
+ interrupts = <0 12 4>;
+ };
+ };
+
+ ttc1: ttc0 at f8002000 {
+ #interrupt-parent = <&intc>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "xlnx,ttc";
+ reg = <0xF8002000 0x1000>;
+ clocks = <&cpu_clk 3>;
+ clock-names = "cpu_1x";
+ clock-ranges;
+
+ ttc1_0: ttc1.0 {
+ status = "disabled";
+ reg = <0>;
+ interrupts = <0 37 4>;
+ };
+ ttc1_1: ttc1.1 {
+ status = "disabled";
+ reg = <1>;
+ interrupts = <0 38 4>;
+ };
+ ttc1_2: ttc1.2 {
+ status = "disabled";
+ reg = <2>;
+ interrupts = <0 39 4>;
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts
index 86f44d5..c772942 100644
--- a/arch/arm/boot/dts/zynq-zc702.dts
+++ b/arch/arm/boot/dts/zynq-zc702.dts
@@ -32,3 +32,13 @@
&ps_clk {
clock-frequency = <33333330>;
};
+
+&ttc0_0 {
+ status = "ok";
+ compatible = "xlnx,ttc-counter-clocksource";
+};
+
+&ttc0_1 {
+ status = "ok";
+ compatible = "xlnx,ttc-counter-clockevent";
+};
diff --git a/drivers/clocksource/xilinx_ttc.c b/drivers/clocksource/xilinx_ttc.c
index ff38b3e..a4718f7 100644
--- a/drivers/clocksource/xilinx_ttc.c
+++ b/drivers/clocksource/xilinx_ttc.c
@@ -23,30 +23,14 @@
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
#include <mach/zynq_soc.h>
-#define IRQ_TIMERCOUNTER0 42
-
-/*
- * This driver configures the 2 16-bit count-up timers as follows:
- *
- * T1: Timer 1, clocksource for generic timekeeping
- * T2: Timer 2, clockevent source for hrtimers
- * T3: Timer 3, <unused>
- *
- * The input frequency to the timer module for emulation is 2.5MHz which is
- * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
- * the timers are clocked at 78.125KHz (12.8 us resolution).
- *
- * The input frequency to the timer module in silicon will be 200MHz. With the
- * pre-scaler of 32, the timers are clocked at 6.25MHz (160ns resolution).
- */
-#define XTTCPSS_CLOCKSOURCE 0 /* Timer 1 as a generic timekeeping */
-#define XTTCPSS_CLOCKEVENT 1 /* Timer 2 as a clock event */
-
-#define XTTCPSS_TIMER_BASE TTC0_BASE
-#define XTTCPCC_EVENT_TIMER_IRQ (IRQ_TIMERCOUNTER0 + 1)
/*
* Timer Register Offset Definitions of Timer 1, Increment base address by 4
* and use same offsets for Timer 2
@@ -63,9 +47,14 @@
#define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1
-/* Setup the timers to use pre-scaling */
-
-#define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32)
+/* Setup the timers to use pre-scaling, using a fixed value for now that will
+ * work across most input frequency, but it may need to be more dynamic
+ */
+#define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */
+#define PRESCALE 2048 /* The exponent must match this */
+#define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1)
+#define CLK_CNTRL_PRESCALE_EN 1
+#define CNT_CNTRL_RESET (1<<4)
/**
* struct xttcpss_timer - This definition defines local timer structure
@@ -73,11 +62,25 @@
* @base_addr: Base address of timer
**/
struct xttcpss_timer {
- void __iomem *base_addr;
+ void __iomem *base_addr;
+};
+
+struct xttcpss_timer_clocksource {
+ struct xttcpss_timer xttc;
+ struct clocksource cs;
};
-static struct xttcpss_timer timers[2];
-static struct clock_event_device xttcpss_clockevent;
+#define to_xttcpss_timer_clksrc(x) \
+ container_of(x, struct xttcpss_timer_clocksource, cs)
+
+struct xttcpss_timer_clockevent {
+ struct xttcpss_timer xttc;
+ struct clock_event_device ce;
+ struct clk *clk;
+};
+
+#define to_xttcpss_timer_clkevent(x) \
+ container_of(x, struct xttcpss_timer_clockevent, ce)
/**
* xttcpss_set_interval - Set the timer interval value
@@ -99,7 +102,7 @@ static void xttcpss_set_interval(struct xttcpss_timer *timer,
/* Reset the counter (0x10) so that it starts from 0, one-shot
mode makes this needed for timing to be right. */
- ctrl_reg |= 0x10;
+ ctrl_reg |= CNT_CNTRL_RESET;
ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
__raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
}
@@ -114,90 +117,31 @@ static void xttcpss_set_interval(struct xttcpss_timer *timer,
**/
static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
{
- struct clock_event_device *evt = &xttcpss_clockevent;
- struct xttcpss_timer *timer = dev_id;
+ struct xttcpss_timer_clockevent *xttce = dev_id;
+ struct xttcpss_timer *timer = &xttce->xttc;
/* Acknowledge the interrupt and call event handler */
__raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
timer->base_addr + XTTCPSS_ISR_OFFSET);
- evt->event_handler(evt);
+ xttce->ce.event_handler(&xttce->ce);
return IRQ_HANDLED;
}
-static struct irqaction event_timer_irq = {
- .name = "xttcpss clockevent",
- .flags = IRQF_DISABLED | IRQF_TIMER,
- .handler = xttcpss_clock_event_interrupt,
-};
-
-/**
- * xttcpss_timer_hardware_init - Initialize the timer hardware
- *
- * Initialize the hardware to start the clock source, get the clock
- * event timer ready to use, and hook up the interrupt.
- **/
-static void __init xttcpss_timer_hardware_init(void)
-{
- /* Setup the clock source counter to be an incrementing counter
- * with no interrupt and it rolls over at 0xFFFF. Pre-scale
- it by 32 also. Let it start running now.
- */
- timers[XTTCPSS_CLOCKSOURCE].base_addr = XTTCPSS_TIMER_BASE;
-
- __raw_writel(0x0, timers[XTTCPSS_CLOCKSOURCE].base_addr +
- XTTCPSS_IER_OFFSET);
- __raw_writel(0x9, timers[XTTCPSS_CLOCKSOURCE].base_addr +
- XTTCPSS_CLK_CNTRL_OFFSET);
- __raw_writel(0x10, timers[XTTCPSS_CLOCKSOURCE].base_addr +
- XTTCPSS_CNT_CNTRL_OFFSET);
-
- /* Setup the clock event timer to be an interval timer which
- * is prescaled by 32 using the interval interrupt. Leave it
- * disabled for now.
- */
-
- timers[XTTCPSS_CLOCKEVENT].base_addr = XTTCPSS_TIMER_BASE + 4;
-
- __raw_writel(0x23, timers[XTTCPSS_CLOCKEVENT].base_addr +
- XTTCPSS_CNT_CNTRL_OFFSET);
- __raw_writel(0x9, timers[XTTCPSS_CLOCKEVENT].base_addr +
- XTTCPSS_CLK_CNTRL_OFFSET);
- __raw_writel(0x1, timers[XTTCPSS_CLOCKEVENT].base_addr +
- XTTCPSS_IER_OFFSET);
-
- /* Setup IRQ the clock event timer */
- event_timer_irq.dev_id = &timers[XTTCPSS_CLOCKEVENT];
- setup_irq(XTTCPCC_EVENT_TIMER_IRQ, &event_timer_irq);
-}
-
/**
- * __raw_readl_cycles - Reads the timer counter register
+ * __xttc_clocksource_read - Reads the timer counter register
*
* returns: Current timer counter register value
**/
-static cycle_t __raw_readl_cycles(struct clocksource *cs)
+static cycle_t __xttc_clocksource_read(struct clocksource *cs)
{
- struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
+ struct xttcpss_timer *timer = &to_xttcpss_timer_clksrc(cs)->xttc;
return (cycle_t)__raw_readl(timer->base_addr +
XTTCPSS_COUNT_VAL_OFFSET);
}
-
-/*
- * Instantiate and initialize the clock source structure
- */
-static struct clocksource clocksource_xttcpss = {
- .name = "xttcpss_timer1",
- .rating = 200, /* Reasonable clock source */
- .read = __raw_readl_cycles,
- .mask = CLOCKSOURCE_MASK(16),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-
/**
* xttcpss_set_next_event - Sets the time interval for next event
*
@@ -209,7 +153,8 @@ static struct clocksource clocksource_xttcpss = {
static int xttcpss_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
- struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+ struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt);
+ struct xttcpss_timer *timer = &xttce->xttc;
xttcpss_set_interval(timer, cycles);
return 0;
@@ -224,12 +169,14 @@ static int xttcpss_set_next_event(unsigned long cycles,
static void xttcpss_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+ struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt);
+ struct xttcpss_timer *timer = &xttce->xttc;
u32 ctrl_reg;
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
- xttcpss_set_interval(timer, TIMER_RATE / HZ);
+ xttcpss_set_interval(timer,
+ clk_get_rate(xttce->clk) / PRESCALE);
break;
case CLOCK_EVT_MODE_ONESHOT:
case CLOCK_EVT_MODE_UNUSED:
@@ -250,15 +197,99 @@ static void xttcpss_set_mode(enum clock_event_mode mode,
}
}
-/*
- * Instantiate and initialize the clock event structure
- */
-static struct clock_event_device xttcpss_clockevent = {
- .name = "xttcpss_timer2",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .set_next_event = xttcpss_set_next_event,
- .set_mode = xttcpss_set_mode,
- .rating = 200,
+static int __init zynq_ttc_setup_clocksource(struct device_node *np,
+ void __iomem *base)
+{
+ struct xttcpss_timer_clocksource *ttccs;
+ struct clk *clk;
+ int err;
+ u32 reg;
+
+ ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL);
+ WARN_ON(!ttccs);
+
+ err = of_property_read_u32(np, "reg", ®);
+ WARN_ON(err);
+
+ clk = of_clk_get_by_name(np, "cpu_1x");
+ WARN_ON(IS_ERR(clk));
+
+ err = clk_prepare_enable(clk);
+ WARN_ON(err);
+
+ ttccs->xttc.base_addr = base + reg * 4;
+
+ ttccs->cs.name = np->name;
+ ttccs->cs.rating = 200;
+ ttccs->cs.read = __xttc_clocksource_read;
+ ttccs->cs.mask = CLOCKSOURCE_MASK(16);
+ ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+ __raw_writel(0x0, ttccs->xttc.base_addr + XTTCPSS_IER_OFFSET);
+ __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
+ ttccs->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET);
+ __raw_writel(CNT_CNTRL_RESET,
+ ttccs->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+
+ err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE);
+ WARN_ON(err);
+
+ return 0;
+}
+
+static int __init zynq_ttc_setup_clockevent(struct device_node *np,
+ void __iomem *base)
+{
+ struct xttcpss_timer_clockevent *ttcce;
+ int err, irq;
+ u32 reg;
+
+ ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL);
+ WARN_ON(!ttcce);
+
+ err = of_property_read_u32(np, "reg", ®);
+ WARN_ON(err);
+
+ ttcce->xttc.base_addr = base + reg * 4;
+
+ ttcce->clk = of_clk_get_by_name(np, "cpu_1x");
+ WARN_ON(IS_ERR(ttcce->clk));
+
+ err = clk_prepare_enable(ttcce->clk);
+ WARN_ON(err);
+
+ irq = irq_of_parse_and_map(np, 0);
+ WARN_ON(!irq);
+
+ ttcce->ce.name = np->name;
+ ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ ttcce->ce.set_next_event = xttcpss_set_next_event;
+ ttcce->ce.set_mode = xttcpss_set_mode;
+ ttcce->ce.rating = 200;
+ ttcce->ce.irq = irq;
+
+ __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+ __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
+ ttcce->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET);
+ __raw_writel(0x1, ttcce->xttc.base_addr + XTTCPSS_IER_OFFSET);
+
+ err = request_irq(irq, xttcpss_clock_event_interrupt, IRQF_TIMER,
+ np->name, ttcce);
+ WARN_ON(err);
+
+ clockevents_config_and_register(&ttcce->ce,
+ clk_get_rate(ttcce->clk) / PRESCALE,
+ 1, 0xfffe);
+
+ return 0;
+}
+
+static const __initconst struct of_device_id zynq_ttc_match[] = {
+ { .compatible = "xlnx,ttc-counter-clocksource",
+ .data = zynq_ttc_setup_clocksource, },
+ { .compatible = "xlnx,ttc-counter-clockevent",
+ .data = zynq_ttc_setup_clockevent, },
+ {}
};
/**
@@ -269,21 +300,27 @@ static struct clock_event_device xttcpss_clockevent = {
**/
void __init xttcpss_timer_init(void)
{
- xttcpss_timer_hardware_init();
- clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "xlnx,ttc") {
+ struct device_node *np_chld;
+ void __iomem *base;
- /* Calculate the parameters to allow the clockevent to operate using
- integer math
- */
- clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4);
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
- xttcpss_clockevent.max_delta_ns =
- clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
- xttcpss_clockevent.min_delta_ns =
- clockevent_delta2ns(1, &xttcpss_clockevent);
+ for_each_available_child_of_node(np, np_chld) {
+ int (*cb)(struct device_node *np, void __iomem *base);
+ const struct of_device_id *match;
- /* Indicate that clock event is on 1st CPU as SMP boot needs it */
+ match = of_match_node(zynq_ttc_match, np_chld);
+ if (match) {
+ int err;
- xttcpss_clockevent.cpumask = cpumask_of(0);
- clockevents_register_device(&xttcpss_clockevent);
+ cb = match->data;
+ err = cb(np_chld, base);
+ WARN_ON(err);
+ }
+ }
+ }
}
--
1.8.0
^ permalink raw reply related
* [PATCH v2 5/5] ARM: zynq: add clk binding support to the ttc
From: Josh Cartwright @ 2012-10-31 19:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1352400580.git.josh.cartwright@ni.com>
Add support for retrieving TTC configuration from device tree. This
includes the ability to pull information about the driving clocks from
the of_clk bindings.
Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
---
arch/arm/boot/dts/zynq-7000.dtsi | 53 ++++++++
arch/arm/boot/dts/zynq-zc702.dts | 10 ++
arch/arm/mach-zynq/timer.c | 287 ++++++++++++++++++++++-----------------
3 files changed, 228 insertions(+), 122 deletions(-)
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index c975c2d..5914b56 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -109,5 +109,58 @@
};
};
};
+
+ ttc0: ttc0 at f8001000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "xlnx,ttc";
+ reg = <0xF8001000 0x1000>;
+ clocks = <&cpu_clk 3>;
+ clock-names = "cpu_1x";
+ clock-ranges;
+
+ ttc0_0: ttc0.0 {
+ status = "disabled";
+ reg = <0>;
+ interrupts = <0 10 4>;
+ };
+ ttc0_1: ttc0.1 {
+ status = "disabled";
+ reg = <1>;
+ interrupts = <0 11 4>;
+ };
+ ttc0_2: ttc0.2 {
+ status = "disabled";
+ reg = <2>;
+ interrupts = <0 12 4>;
+ };
+ };
+
+ ttc1: ttc1 at f8002000 {
+ #interrupt-parent = <&intc>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "xlnx,ttc";
+ reg = <0xF8002000 0x1000>;
+ clocks = <&cpu_clk 3>;
+ clock-names = "cpu_1x";
+ clock-ranges;
+
+ ttc1_0: ttc1.0 {
+ status = "disabled";
+ reg = <0>;
+ interrupts = <0 37 4>;
+ };
+ ttc1_1: ttc1.1 {
+ status = "disabled";
+ reg = <1>;
+ interrupts = <0 38 4>;
+ };
+ ttc1_2: ttc1.2 {
+ status = "disabled";
+ reg = <2>;
+ interrupts = <0 39 4>;
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts
index 86f44d5..c772942 100644
--- a/arch/arm/boot/dts/zynq-zc702.dts
+++ b/arch/arm/boot/dts/zynq-zc702.dts
@@ -32,3 +32,13 @@
&ps_clk {
clock-frequency = <33333330>;
};
+
+&ttc0_0 {
+ status = "ok";
+ compatible = "xlnx,ttc-counter-clocksource";
+};
+
+&ttc0_1 {
+ status = "ok";
+ compatible = "xlnx,ttc-counter-clockevent";
+};
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
index c93cbe5..9662306 100644
--- a/arch/arm/mach-zynq/timer.c
+++ b/arch/arm/mach-zynq/timer.c
@@ -23,31 +23,15 @@
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
#include <mach/zynq_soc.h>
#include "common.h"
-#define IRQ_TIMERCOUNTER0 42
-
-/*
- * This driver configures the 2 16-bit count-up timers as follows:
- *
- * T1: Timer 1, clocksource for generic timekeeping
- * T2: Timer 2, clockevent source for hrtimers
- * T3: Timer 3, <unused>
- *
- * The input frequency to the timer module for emulation is 2.5MHz which is
- * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
- * the timers are clocked at 78.125KHz (12.8 us resolution).
- *
- * The input frequency to the timer module in silicon will be 200MHz. With the
- * pre-scaler of 32, the timers are clocked at 6.25MHz (160ns resolution).
- */
-#define XTTCPSS_CLOCKSOURCE 0 /* Timer 1 as a generic timekeeping */
-#define XTTCPSS_CLOCKEVENT 1 /* Timer 2 as a clock event */
-
-#define XTTCPSS_TIMER_BASE TTC0_BASE
-#define XTTCPCC_EVENT_TIMER_IRQ (IRQ_TIMERCOUNTER0 + 1)
/*
* Timer Register Offset Definitions of Timer 1, Increment base address by 4
* and use same offsets for Timer 2
@@ -64,9 +48,14 @@
#define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1
-/* Setup the timers to use pre-scaling */
-
-#define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32)
+/* Setup the timers to use pre-scaling, using a fixed value for now that will
+ * work across most input frequency, but it may need to be more dynamic
+ */
+#define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */
+#define PRESCALE 2048 /* The exponent must match this */
+#define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1)
+#define CLK_CNTRL_PRESCALE_EN 1
+#define CNT_CNTRL_RESET (1<<4)
/**
* struct xttcpss_timer - This definition defines local timer structure
@@ -74,11 +63,25 @@
* @base_addr: Base address of timer
**/
struct xttcpss_timer {
- void __iomem *base_addr;
+ void __iomem *base_addr;
+};
+
+struct xttcpss_timer_clocksource {
+ struct xttcpss_timer xttc;
+ struct clocksource cs;
};
-static struct xttcpss_timer timers[2];
-static struct clock_event_device xttcpss_clockevent;
+#define to_xttcpss_timer_clksrc(x) \
+ container_of(x, struct xttcpss_timer_clocksource, cs)
+
+struct xttcpss_timer_clockevent {
+ struct xttcpss_timer xttc;
+ struct clock_event_device ce;
+ struct clk *clk;
+};
+
+#define to_xttcpss_timer_clkevent(x) \
+ container_of(x, struct xttcpss_timer_clockevent, ce)
/**
* xttcpss_set_interval - Set the timer interval value
@@ -100,7 +103,7 @@ static void xttcpss_set_interval(struct xttcpss_timer *timer,
/* Reset the counter (0x10) so that it starts from 0, one-shot
mode makes this needed for timing to be right. */
- ctrl_reg |= 0x10;
+ ctrl_reg |= CNT_CNTRL_RESET;
ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
__raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
}
@@ -115,90 +118,31 @@ static void xttcpss_set_interval(struct xttcpss_timer *timer,
**/
static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
{
- struct clock_event_device *evt = &xttcpss_clockevent;
- struct xttcpss_timer *timer = dev_id;
+ struct xttcpss_timer_clockevent *xttce = dev_id;
+ struct xttcpss_timer *timer = &xttce->xttc;
/* Acknowledge the interrupt and call event handler */
__raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
timer->base_addr + XTTCPSS_ISR_OFFSET);
- evt->event_handler(evt);
+ xttce->ce.event_handler(&xttce->ce);
return IRQ_HANDLED;
}
-static struct irqaction event_timer_irq = {
- .name = "xttcpss clockevent",
- .flags = IRQF_DISABLED | IRQF_TIMER,
- .handler = xttcpss_clock_event_interrupt,
-};
-
/**
- * xttcpss_timer_hardware_init - Initialize the timer hardware
- *
- * Initialize the hardware to start the clock source, get the clock
- * event timer ready to use, and hook up the interrupt.
- **/
-static void __init xttcpss_timer_hardware_init(void)
-{
- /* Setup the clock source counter to be an incrementing counter
- * with no interrupt and it rolls over at 0xFFFF. Pre-scale
- it by 32 also. Let it start running now.
- */
- timers[XTTCPSS_CLOCKSOURCE].base_addr = XTTCPSS_TIMER_BASE;
-
- __raw_writel(0x0, timers[XTTCPSS_CLOCKSOURCE].base_addr +
- XTTCPSS_IER_OFFSET);
- __raw_writel(0x9, timers[XTTCPSS_CLOCKSOURCE].base_addr +
- XTTCPSS_CLK_CNTRL_OFFSET);
- __raw_writel(0x10, timers[XTTCPSS_CLOCKSOURCE].base_addr +
- XTTCPSS_CNT_CNTRL_OFFSET);
-
- /* Setup the clock event timer to be an interval timer which
- * is prescaled by 32 using the interval interrupt. Leave it
- * disabled for now.
- */
-
- timers[XTTCPSS_CLOCKEVENT].base_addr = XTTCPSS_TIMER_BASE + 4;
-
- __raw_writel(0x23, timers[XTTCPSS_CLOCKEVENT].base_addr +
- XTTCPSS_CNT_CNTRL_OFFSET);
- __raw_writel(0x9, timers[XTTCPSS_CLOCKEVENT].base_addr +
- XTTCPSS_CLK_CNTRL_OFFSET);
- __raw_writel(0x1, timers[XTTCPSS_CLOCKEVENT].base_addr +
- XTTCPSS_IER_OFFSET);
-
- /* Setup IRQ the clock event timer */
- event_timer_irq.dev_id = &timers[XTTCPSS_CLOCKEVENT];
- setup_irq(XTTCPCC_EVENT_TIMER_IRQ, &event_timer_irq);
-}
-
-/**
- * __raw_readl_cycles - Reads the timer counter register
+ * __xttc_clocksource_read - Reads the timer counter register
*
* returns: Current timer counter register value
**/
-static cycle_t __raw_readl_cycles(struct clocksource *cs)
+static cycle_t __xttc_clocksource_read(struct clocksource *cs)
{
- struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
+ struct xttcpss_timer *timer = &to_xttcpss_timer_clksrc(cs)->xttc;
return (cycle_t)__raw_readl(timer->base_addr +
XTTCPSS_COUNT_VAL_OFFSET);
}
-
-/*
- * Instantiate and initialize the clock source structure
- */
-static struct clocksource clocksource_xttcpss = {
- .name = "xttcpss_timer1",
- .rating = 200, /* Reasonable clock source */
- .read = __raw_readl_cycles,
- .mask = CLOCKSOURCE_MASK(16),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-
/**
* xttcpss_set_next_event - Sets the time interval for next event
*
@@ -210,7 +154,8 @@ static struct clocksource clocksource_xttcpss = {
static int xttcpss_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
- struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+ struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt);
+ struct xttcpss_timer *timer = &xttce->xttc;
xttcpss_set_interval(timer, cycles);
return 0;
@@ -225,12 +170,15 @@ static int xttcpss_set_next_event(unsigned long cycles,
static void xttcpss_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+ struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt);
+ struct xttcpss_timer *timer = &xttce->xttc;
u32 ctrl_reg;
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
- xttcpss_set_interval(timer, TIMER_RATE / HZ);
+ xttcpss_set_interval(timer,
+ DIV_ROUND_CLOSEST(clk_get_rate(xttce->clk),
+ PRESCALE * HZ));
break;
case CLOCK_EVT_MODE_ONESHOT:
case CLOCK_EVT_MODE_UNUSED:
@@ -251,15 +199,106 @@ static void xttcpss_set_mode(enum clock_event_mode mode,
}
}
-/*
- * Instantiate and initialize the clock event structure
- */
-static struct clock_event_device xttcpss_clockevent = {
- .name = "xttcpss_timer2",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .set_next_event = xttcpss_set_next_event,
- .set_mode = xttcpss_set_mode,
- .rating = 200,
+static void __init zynq_ttc_setup_clocksource(struct device_node *np,
+ void __iomem *base)
+{
+ struct xttcpss_timer_clocksource *ttccs;
+ struct clk *clk;
+ int err;
+ u32 reg;
+
+ ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL);
+ if (WARN_ON(!ttccs))
+ return;
+
+ err = of_property_read_u32(np, "reg", ®);
+ if (WARN_ON(err))
+ return;
+
+ clk = of_clk_get_by_name(np, "cpu_1x");
+ if (WARN_ON(IS_ERR(clk)))
+ return;
+
+ err = clk_prepare_enable(clk);
+ if (WARN_ON(err))
+ return;
+
+ ttccs->xttc.base_addr = base + reg * 4;
+
+ ttccs->cs.name = np->name;
+ ttccs->cs.rating = 200;
+ ttccs->cs.read = __xttc_clocksource_read;
+ ttccs->cs.mask = CLOCKSOURCE_MASK(16);
+ ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+ __raw_writel(0x0, ttccs->xttc.base_addr + XTTCPSS_IER_OFFSET);
+ __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
+ ttccs->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET);
+ __raw_writel(CNT_CNTRL_RESET,
+ ttccs->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+
+ err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE);
+ if (WARN_ON(err))
+ return;
+}
+
+static void __init zynq_ttc_setup_clockevent(struct device_node *np,
+ void __iomem *base)
+{
+ struct xttcpss_timer_clockevent *ttcce;
+ int err, irq;
+ u32 reg;
+
+ ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL);
+ if (WARN_ON(!ttcce))
+ return;
+
+ err = of_property_read_u32(np, "reg", ®);
+ if (WARN_ON(err))
+ return;
+
+ ttcce->xttc.base_addr = base + reg * 4;
+
+ ttcce->clk = of_clk_get_by_name(np, "cpu_1x");
+ if (WARN_ON(IS_ERR(ttcce->clk)))
+ return;
+
+ err = clk_prepare_enable(ttcce->clk);
+ if (WARN_ON(err))
+ return;
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (WARN_ON(!irq))
+ return;
+
+ ttcce->ce.name = np->name;
+ ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ ttcce->ce.set_next_event = xttcpss_set_next_event;
+ ttcce->ce.set_mode = xttcpss_set_mode;
+ ttcce->ce.rating = 200;
+ ttcce->ce.irq = irq;
+
+ __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+ __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
+ ttcce->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET);
+ __raw_writel(0x1, ttcce->xttc.base_addr + XTTCPSS_IER_OFFSET);
+
+ err = request_irq(irq, xttcpss_clock_event_interrupt, IRQF_TIMER,
+ np->name, ttcce);
+ if (WARN_ON(err))
+ return;
+
+ clockevents_config_and_register(&ttcce->ce,
+ clk_get_rate(ttcce->clk) / PRESCALE,
+ 1, 0xfffe);
+}
+
+static const __initconst struct of_device_id zynq_ttc_match[] = {
+ { .compatible = "xlnx,ttc-counter-clocksource",
+ .data = zynq_ttc_setup_clocksource, },
+ { .compatible = "xlnx,ttc-counter-clockevent",
+ .data = zynq_ttc_setup_clockevent, },
+ {}
};
/**
@@ -270,21 +309,25 @@ static struct clock_event_device xttcpss_clockevent = {
**/
void __init xttcpss_timer_init(void)
{
- xttcpss_timer_hardware_init();
- clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
-
- /* Calculate the parameters to allow the clockevent to operate using
- integer math
- */
- clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4);
-
- xttcpss_clockevent.max_delta_ns =
- clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
- xttcpss_clockevent.min_delta_ns =
- clockevent_delta2ns(1, &xttcpss_clockevent);
-
- /* Indicate that clock event is on 1st CPU as SMP boot needs it */
-
- xttcpss_clockevent.cpumask = cpumask_of(0);
- clockevents_register_device(&xttcpss_clockevent);
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "xlnx,ttc") {
+ struct device_node *np_chld;
+ void __iomem *base;
+
+ base = of_iomap(np, 0);
+ if (WARN_ON(!base))
+ return;
+
+ for_each_available_child_of_node(np, np_chld) {
+ int (*cb)(struct device_node *np, void __iomem *base);
+ const struct of_device_id *match;
+
+ match = of_match_node(zynq_ttc_match, np_chld);
+ if (match) {
+ cb = match->data;
+ cb(np_chld, base);
+ }
+ }
+ }
}
--
1.8.0
^ permalink raw reply related
* [PATCHv2] Input: omap4-keypad: Add pinctrl support
From: Kevin Hilman @ 2012-10-31 20:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdapQJY0aoam741O0fb8EeM9BLk_Psq5TaPG84J7wEvCLw@mail.gmail.com>
Linus Walleij <linus.walleij@linaro.org> writes:
> On Tue, Oct 30, 2012 at 12:34 PM, Mark Brown
> <broonie@opensource.wolfsonmicro.com> wrote:
>> On Sun, Oct 28, 2012 at 09:12:52PM +0100, Linus Walleij wrote:
>
>>> Moving this handling to bus code or anywhere else
>>> invariably implies that resource acquisition/release order
>>> does not matter, and my point is that it does.
>>
>> Doing this in the buses is definitely wrong, as you say it's not bus
>> specific. I do however think we can usefully do this stuff in a SoC
>> specific place like a power domain, keeping the SoC integration code
>> together and out of the drivers. IME the SoCs where you need to do
>> different things for different IPs shoudl mostly still get some reuse
>> out of such an approach.
>
> Talking to Kevin Hilman today he was also stressing that
> power domains is a good thing for handling resources, especially
> when replacing prior hacks in the custom clk code. However
> he pointed specifically to clocks and voltages, which may
> be true.
>
> What worries me is when knowledge of the hardware which
> is traditionally a concern for the device driver start to
> bubble up to the power domain (or better renamed resource
> domain if use like this, as Felipe points out).
>
> I worry that we will end up with power/resource domain
> code that start to look like this:
>
> suspend()
> switch (device.id) {
> case DEV_FOO:
> clk_disable();
> pinctrl_set_state();
> power_domain_off();
> case DEV_BAR:
> pinctrl_set_state();
> clk_disable();
> // Always-on domain
> case DEV_BAZ:
> pinctrl_set_state();
> clk_disable();
> power_domain_off();
> case ...
>
> Mutate the above with silicon errata, specific tweaks etc that
> Felipe was mentioning.
like this, as well as a bunch more. This is why we have a generic
description of IP blocks (omap_hwmod) which abstracts all of these
differences and keeps the PM domain layer rather simple.
I agree with Mark. Either you have to take care of this with
conditional code in the driver, and the drivers become bloated with a
mess of SoC integration details, or you hide it away in SoC-specific
code that can handle this, and keep the drivers portable.
Now that we have PM domains (PM domains didn't exist when we created
omap_device/omap_hwmod), I suspect the cleanest way to do this is to
create separate PM domains for each "class" of devices that have
different set of behavior.
> What is happening is that device-specific behaviour which
> traditionally handled in the driver is now inside the
> power/resource domain.
>
> piece of hardware, this would be the right thing to do,
> and I think the in-kernel examples are all "simple",
> e.g. arch/arm/mach-omap2/powerdomain* is all about
> power domains and nothing else,
FYI... that code isn't the same as PM domain. That code is for the
*hardware* powerdomains, not the software concept of "PM domain." In
OMAP, PM domain is implmented at the omap_device level. And omap_device
is the abstraction of an IP block that knows about all the PM related
register settings, clocks, HW powerdomain, voltage domain, PM related
pin-muxing etc. etc. All of these things are abstracted in an
omap_device, so that the PM domain implementation for OMAP looks rather
simple (c.f. omap_device_pm_domain in arch/arm/plat-omap/omap_device.c.)
Note that the callbacks just call omap_device_enable(),
omap_device_disable() and all the HW ugliness, SoC-specific integration
mess is hidden away.
[...]
> I think the lesser of two evils is the distributed approach,
> and then I'm talking about pinctrl only, disregarding the
> fact that clocks and power domains are basically subject to
> the same kind of argument. I still buy into the concept of
> using power domains for exactly power domains only.
> Arguably this is an elegance opinion...
The pinctrl examples I've seen mentioned so far are all PM related
(sleep, idle, wakeup, etc.) so to me I think they still belong in
PM domains (and that's how we handle the PM related pins in OMAP.)
> I worry that the per-SoC power domain implementation
> which will live in arch/arm/mach-* as of today will become
> the new board file problem, overburdening the arch/* tree.
> Maybe I'm mistaken as to the size of these things,
> but just doing ls arch/arm/mach-omap2/powerdomain*
> makes me start worrying.
Yes, I agree that this means more code/data in arch/arm/mach-*, but
IMO, that's really where it belongs. It really is SoC integration
details, and driver should really not know about it.
Kevin
^ permalink raw reply
* [PATCH V3] mmc: omap_hsmmc: Enable HSPE bit for high speed cards
From: Felipe Balbi @ 2012-10-31 20:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOyx1LrKBE+xzSRN4F=+e1DuMJL+5SAv-YkJWJdDw8p=kDojmw@mail.gmail.com>
Hi,
On Thu, Nov 01, 2012 at 01:21:36AM +0530, Venkatraman S wrote:
> On Wed, Oct 31, 2012 at 5:56 PM, Felipe Balbi <balbi@ti.com> wrote:
> > Hi,
> >
> > On Wed, Oct 31, 2012 at 05:27:36PM +0530, Hebbar, Gururaja wrote:
> >> HSMMC IP on AM33xx need a special setting to handle High-speed cards.
> >> Other platforms like TI81xx, OMAP4 may need this as-well. This depends
> >> on the HSMMC IP timing closure done for the high speed cards.
> >>
> >> From AM335x TRM (SPRUH73F - 18.3.12 Output Signals Generation)
> >>
> >> The MMC/SD/SDIO output signals can be driven on either falling edge or
> >> rising edge depending on the SD_HCTL[2] HSPE bit. This feature allows
> >> to reach better timing performance, and thus to increase data transfer
> >> frequency.
> >>
> >> There are few pre-requisites for enabling the HSPE bit
> >> - Controller should support High-Speed-Enable Bit and
> >> - Controller should not be using DDR Mode and
> >> - Controller should advertise that it supports High Speed in
> >> capabilities register and
> >> - MMC/SD clock coming out of controller > 25MHz
> >>
> >> Note:
> >> The implementation reuses the output of calc_divisor() so as to reduce
> >> code addition.
> >>
> >> Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>
> >
> > this looks good to my eyes, hopefully I haven't missed anything:
> >
> > Reviewed-by: Felipe Balbi <balbi@ti.com>
> >
>
> Except for the excessively verbose comments which are just duplicating the code,
> <Quote>
> >> + * Enable High-Speed Support
> >> + * Pre-Requisites
> >> + * - Controller should support High-Speed-Enable Bit
> >> + * - Controller should not be using DDR Mode
> >> + * - Controller should advertise that it supports High Speed
> >> + * in capabilities register
> >> + * - MMC/SD clock coming out of controller > 25MHz
> >> + */
> </Quote>
>
> I'm ok with this patch as well. I'm putting a few patches under test
> including this one,
> and will send it to Chris as part of that series.
> I'll strip out the above mentioned comments, unless there are any
> objections.
please don't. Detailing the pre-requisites for getting HSP mode working
isn't bad at all. Should someone decide to change the behavior and ends
up breaking it, the comment will help putting things back together.
my 2 cents, you've got the final decision though.
--
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121031/341e1607/attachment-0001.sig>
^ permalink raw reply
* [PATCH V4 0/7] ARM: tegra30: cpuidle: add a powered-down state
From: Stephen Warren @ 2012-10-31 20:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351676481-28425-1-git-send-email-josephl@nvidia.com>
On 10/31/2012 03:41 AM, Joseph Lo wrote:
> This adds a "powered-down" state for cpuidle. It's a power gating idle
> mode. It supports the secondary CPUs (i.e., CPU1-CPU3) to go into
> powered-down state independently. When any of the secondary CPUs go into
> this state, it can be power gated alone. There is a limitation on CPU0.
> The CPU0 can go into powered-down state only when all secondary CPU is
> offline. After CPU0 is in powered-down state, the CPU rail can be turned
> off.
>
> All CPUs entering powered-down state is not working. The CPU0 enters this
> state only when secondary CPU is offline. This can be coverd by CPUquiet
> and cluster switching mechanism.
OK, this appears to work OK. I have applied it to Tegra's
for-3.8/cpuidle branch.
> V4:
> * rebased on next-20121031
Purely as an FYI, being based on top of Tegra's for-3.8/cpuidle or
for-next branches would have been even better, although in practice this
time around, there were no conflicts applying it there.
^ permalink raw reply
* [PATCH 1/6] arch: Change defconfigs to point to g_mass_storage.
From: Michal Nazarewicz @ 2012-10-31 20:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1351715302.git.mina86@mina86.com>
From: Michal Nazarewicz <mina86@mina86.com>
The File-backed Storage Gadget (g_file_storage) is being removed, since
it has been replaced by Mass Storage Gadget (g_mass_storage). This commit
changes defconfigs point to the new gadget.
Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
---
arch/arm/configs/afeb9260_defconfig | 2 +-
arch/arm/configs/at91sam9260_defconfig | 2 +-
arch/arm/configs/at91sam9261_defconfig | 2 +-
arch/arm/configs/at91sam9263_defconfig | 2 +-
arch/arm/configs/at91sam9g20_defconfig | 2 +-
arch/arm/configs/corgi_defconfig | 2 +-
arch/arm/configs/davinci_all_defconfig | 2 +-
arch/arm/configs/h7202_defconfig | 3 +--
arch/arm/configs/magician_defconfig | 2 +-
arch/arm/configs/mini2440_defconfig | 2 +-
arch/arm/configs/omap1_defconfig | 3 +--
arch/arm/configs/prima2_defconfig | 1 -
arch/arm/configs/qil-a9260_defconfig | 1 -
arch/arm/configs/spitz_defconfig | 2 +-
arch/arm/configs/stamp9g20_defconfig | 2 +-
arch/arm/configs/viper_defconfig | 2 +-
arch/arm/configs/zeus_defconfig | 2 +-
arch/avr32/configs/atngw100_defconfig | 2 +-
arch/avr32/configs/atngw100_evklcd100_defconfig | 2 +-
arch/avr32/configs/atngw100_evklcd101_defconfig | 2 +-
arch/avr32/configs/atngw100_mrmt_defconfig | 2 +-
arch/avr32/configs/atngw100mkii_defconfig | 2 +-
.../avr32/configs/atngw100mkii_evklcd100_defconfig | 2 +-
.../avr32/configs/atngw100mkii_evklcd101_defconfig | 2 +-
arch/avr32/configs/atstk1002_defconfig | 2 +-
arch/avr32/configs/atstk1003_defconfig | 2 +-
arch/avr32/configs/atstk1004_defconfig | 2 +-
arch/avr32/configs/atstk1006_defconfig | 2 +-
arch/avr32/configs/favr-32_defconfig | 2 +-
arch/avr32/configs/hammerhead_defconfig | 2 +-
arch/blackfin/configs/CM-BF527_defconfig | 2 +-
arch/blackfin/configs/CM-BF548_defconfig | 2 +-
arch/blackfin/configs/CM-BF561_defconfig | 2 +-
arch/mips/configs/bcm47xx_defconfig | 2 +-
arch/mips/configs/mtx1_defconfig | 2 +-
arch/sh/configs/ecovec24_defconfig | 2 +-
arch/sh/configs/se7724_defconfig | 2 +-
37 files changed, 35 insertions(+), 39 deletions(-)
diff --git a/arch/arm/configs/afeb9260_defconfig b/arch/arm/configs/afeb9260_defconfig
index c285a9d..a8dbc1e 100644
--- a/arch/arm/configs/afeb9260_defconfig
+++ b/arch/arm/configs/afeb9260_defconfig
@@ -79,7 +79,7 @@ CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_RTC_CLASS=y
CONFIG_RTC_DEBUG=y
diff --git a/arch/arm/configs/at91sam9260_defconfig b/arch/arm/configs/at91sam9260_defconfig
index 505b376..0ea5d2c 100644
--- a/arch/arm/configs/at91sam9260_defconfig
+++ b/arch/arm/configs/at91sam9260_defconfig
@@ -75,7 +75,7 @@ CONFIG_USB_STORAGE_DEBUG=y
CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_AT91SAM9=y
diff --git a/arch/arm/configs/at91sam9261_defconfig b/arch/arm/configs/at91sam9261_defconfig
index 1e8712e..c87beb9 100644
--- a/arch/arm/configs/at91sam9261_defconfig
+++ b/arch/arm/configs/at91sam9261_defconfig
@@ -125,7 +125,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=m
diff --git a/arch/arm/configs/at91sam9263_defconfig b/arch/arm/configs/at91sam9263_defconfig
index d2050ca..c5212f4 100644
--- a/arch/arm/configs/at91sam9263_defconfig
+++ b/arch/arm/configs/at91sam9263_defconfig
@@ -133,7 +133,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_SDIO_UART=m
diff --git a/arch/arm/configs/at91sam9g20_defconfig b/arch/arm/configs/at91sam9g20_defconfig
index e1b0e80..3b18810 100644
--- a/arch/arm/configs/at91sam9g20_defconfig
+++ b/arch/arm/configs/at91sam9g20_defconfig
@@ -96,7 +96,7 @@ CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=m
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 4b8a25d..1fd1d1d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -218,7 +218,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_PXA=y
diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
index 67b5abb6..4ea7c95 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -144,7 +144,7 @@ CONFIG_USB_GADGET_DEBUG_FS=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_PRINTER=m
CONFIG_USB_CDC_COMPOSITE=m
diff --git a/arch/arm/configs/h7202_defconfig b/arch/arm/configs/h7202_defconfig
index 69405a7..e16d3f3 100644
--- a/arch/arm/configs/h7202_defconfig
+++ b/arch/arm/configs/h7202_defconfig
@@ -34,8 +34,7 @@ CONFIG_FB_MODE_HELPERS=y
CONFIG_USB_GADGET=m
CONFIG_USB_ZERO=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_EXT2_FS=y
CONFIG_TMPFS=y
diff --git a/arch/arm/configs/magician_defconfig b/arch/arm/configs/magician_defconfig
index a691ef4..557dd29 100644
--- a/arch/arm/configs/magician_defconfig
+++ b/arch/arm/configs/magician_defconfig
@@ -136,7 +136,7 @@ CONFIG_USB_PXA27X=y
CONFIG_USB_ETH=m
# CONFIG_USB_ETH_RNDIS is not set
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_USB_GPIO_VBUS=y
diff --git a/arch/arm/configs/mini2440_defconfig b/arch/arm/configs/mini2440_defconfig
index 00630e6..a07948a 100644
--- a/arch/arm/configs/mini2440_defconfig
+++ b/arch/arm/configs/mini2440_defconfig
@@ -240,7 +240,7 @@ CONFIG_USB_GADGET_S3C2410=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
diff --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/omap1_defconfig
index dde2a1a..42eab9a 100644
--- a/arch/arm/configs/omap1_defconfig
+++ b/arch/arm/configs/omap1_defconfig
@@ -214,8 +214,7 @@ CONFIG_USB_TEST=y
CONFIG_USB_GADGET=y
CONFIG_USB_ETH=m
# CONFIG_USB_ETH_RNDIS is not set
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_MASS_STORAGE=m
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
diff --git a/arch/arm/configs/prima2_defconfig b/arch/arm/configs/prima2_defconfig
index 807d4e2..6a936c7 100644
--- a/arch/arm/configs/prima2_defconfig
+++ b/arch/arm/configs/prima2_defconfig
@@ -37,7 +37,6 @@ CONFIG_SPI_SIRF=y
CONFIG_SPI_SPIDEV=y
# CONFIG_HWMON is not set
CONFIG_USB_GADGET=y
-CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
diff --git a/arch/arm/configs/qil-a9260_defconfig b/arch/arm/configs/qil-a9260_defconfig
index 42d5db1..41a88db 100644
--- a/arch/arm/configs/qil-a9260_defconfig
+++ b/arch/arm/configs/qil-a9260_defconfig
@@ -108,7 +108,6 @@ CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_850=y
CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index df77931..2e0419d 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -214,7 +214,7 @@ CONFIG_USB_GADGET_DUMMY_HCD=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_PXA=y
diff --git a/arch/arm/configs/stamp9g20_defconfig b/arch/arm/configs/stamp9g20_defconfig
index 52f1488..b845f55 100644
--- a/arch/arm/configs/stamp9g20_defconfig
+++ b/arch/arm/configs/stamp9g20_defconfig
@@ -97,7 +97,7 @@ CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=m
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index 1d01ddd..d36e0d3 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -139,7 +139,7 @@ CONFIG_USB_SERIAL_MCT_U232=m
CONFIG_USB_GADGET=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_PRINTER=m
CONFIG_RTC_CLASS=y
diff --git a/arch/arm/configs/zeus_defconfig b/arch/arm/configs/zeus_defconfig
index 547a3c1..731d4f9 100644
--- a/arch/arm/configs/zeus_defconfig
+++ b/arch/arm/configs/zeus_defconfig
@@ -143,7 +143,7 @@ CONFIG_USB_GADGET=m
CONFIG_USB_PXA27X=y
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_PRINTER=m
CONFIG_MMC=y
diff --git a/arch/avr32/configs/atngw100_defconfig b/arch/avr32/configs/atngw100_defconfig
index a06bfcc..f4025db 100644
--- a/arch/avr32/configs/atngw100_defconfig
+++ b/arch/avr32/configs/atngw100_defconfig
@@ -109,7 +109,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
diff --git a/arch/avr32/configs/atngw100_evklcd100_defconfig b/arch/avr32/configs/atngw100_evklcd100_defconfig
index d8f1fe8..c76a49b 100644
--- a/arch/avr32/configs/atngw100_evklcd100_defconfig
+++ b/arch/avr32/configs/atngw100_evklcd100_defconfig
@@ -125,7 +125,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
diff --git a/arch/avr32/configs/atngw100_evklcd101_defconfig b/arch/avr32/configs/atngw100_evklcd101_defconfig
index d4c5b19..2d8ab08 100644
--- a/arch/avr32/configs/atngw100_evklcd101_defconfig
+++ b/arch/avr32/configs/atngw100_evklcd101_defconfig
@@ -124,7 +124,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
diff --git a/arch/avr32/configs/atngw100_mrmt_defconfig b/arch/avr32/configs/atngw100_mrmt_defconfig
index 77ca4f9..b189e0c 100644
--- a/arch/avr32/configs/atngw100_mrmt_defconfig
+++ b/arch/avr32/configs/atngw100_mrmt_defconfig
@@ -99,7 +99,7 @@ CONFIG_SND_ATMEL_AC97C=m
# CONFIG_SND_SPI is not set
CONFIG_USB_GADGET=m
CONFIG_USB_GADGET_DEBUG_FILES=y
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=y
diff --git a/arch/avr32/configs/atngw100mkii_defconfig b/arch/avr32/configs/atngw100mkii_defconfig
index 6e0dca4..2e4de42 100644
--- a/arch/avr32/configs/atngw100mkii_defconfig
+++ b/arch/avr32/configs/atngw100mkii_defconfig
@@ -111,7 +111,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
diff --git a/arch/avr32/configs/atngw100mkii_evklcd100_defconfig b/arch/avr32/configs/atngw100mkii_evklcd100_defconfig
index 7f2a344..fad3cd2 100644
--- a/arch/avr32/configs/atngw100mkii_evklcd100_defconfig
+++ b/arch/avr32/configs/atngw100mkii_evklcd100_defconfig
@@ -128,7 +128,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
diff --git a/arch/avr32/configs/atngw100mkii_evklcd101_defconfig b/arch/avr32/configs/atngw100mkii_evklcd101_defconfig
index 085eeba..2998623 100644
--- a/arch/avr32/configs/atngw100mkii_evklcd101_defconfig
+++ b/arch/avr32/configs/atngw100mkii_evklcd101_defconfig
@@ -127,7 +127,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig
index d1a887e..a582465 100644
--- a/arch/avr32/configs/atstk1002_defconfig
+++ b/arch/avr32/configs/atstk1002_defconfig
@@ -126,7 +126,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
diff --git a/arch/avr32/configs/atstk1003_defconfig b/arch/avr32/configs/atstk1003_defconfig
index 956f281..57a79df 100644
--- a/arch/avr32/configs/atstk1003_defconfig
+++ b/arch/avr32/configs/atstk1003_defconfig
@@ -105,7 +105,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
diff --git a/arch/avr32/configs/atstk1004_defconfig b/arch/avr32/configs/atstk1004_defconfig
index 40c69f3..1a49bd8 100644
--- a/arch/avr32/configs/atstk1004_defconfig
+++ b/arch/avr32/configs/atstk1004_defconfig
@@ -104,7 +104,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
diff --git a/arch/avr32/configs/atstk1006_defconfig b/arch/avr32/configs/atstk1006_defconfig
index 511eb8a..206a1b6 100644
--- a/arch/avr32/configs/atstk1006_defconfig
+++ b/arch/avr32/configs/atstk1006_defconfig
@@ -129,7 +129,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
diff --git a/arch/avr32/configs/favr-32_defconfig b/arch/avr32/configs/favr-32_defconfig
index 19973b0..0421498 100644
--- a/arch/avr32/configs/favr-32_defconfig
+++ b/arch/avr32/configs/favr-32_defconfig
@@ -117,7 +117,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
diff --git a/arch/avr32/configs/hammerhead_defconfig b/arch/avr32/configs/hammerhead_defconfig
index 6f45681..82f24eb 100644
--- a/arch/avr32/configs/hammerhead_defconfig
+++ b/arch/avr32/configs/hammerhead_defconfig
@@ -127,7 +127,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=m
CONFIG_MMC_ATMELMCI=m
diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig
index c280a50..f59c80e 100644
--- a/arch/blackfin/configs/CM-BF527_defconfig
+++ b/arch/blackfin/configs/CM-BF527_defconfig
@@ -106,7 +106,7 @@ CONFIG_MUSB_PIO_ONLY=y
CONFIG_USB_STORAGE=m
CONFIG_USB_GADGET=m
CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_PRINTER=m
CONFIG_RTC_CLASS=y
diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig
index 349922b..e961483 100644
--- a/arch/blackfin/configs/CM-BF548_defconfig
+++ b/arch/blackfin/configs/CM-BF548_defconfig
@@ -107,7 +107,7 @@ CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
# CONFIG_USB_ETH_RNDIS is not set
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_PRINTER=m
CONFIG_MMC=m
diff --git a/arch/blackfin/configs/CM-BF561_defconfig b/arch/blackfin/configs/CM-BF561_defconfig
index 0456dea..24936b9 100644
--- a/arch/blackfin/configs/CM-BF561_defconfig
+++ b/arch/blackfin/configs/CM-BF561_defconfig
@@ -83,7 +83,7 @@ CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_USB_GADGET=m
CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_PRINTER=m
CONFIG_MMC=y
diff --git a/arch/mips/configs/bcm47xx_defconfig b/arch/mips/configs/bcm47xx_defconfig
index b6fde2b..4ca8e5c 100644
--- a/arch/mips/configs/bcm47xx_defconfig
+++ b/arch/mips/configs/bcm47xx_defconfig
@@ -473,7 +473,7 @@ CONFIG_USB_GADGET_NET2280=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_MIDI_GADGET=m
CONFIG_LEDS_CLASS=y
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index 46c61edc..a0277d4 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -661,7 +661,7 @@ CONFIG_USB_GADGET_NET2280=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_MIDI_GADGET=m
CONFIG_MMC=m
diff --git a/arch/sh/configs/ecovec24_defconfig b/arch/sh/configs/ecovec24_defconfig
index 911e30c9..c6c2bec 100644
--- a/arch/sh/configs/ecovec24_defconfig
+++ b/arch/sh/configs/ecovec24_defconfig
@@ -112,7 +112,7 @@ CONFIG_USB_MON=y
CONFIG_USB_R8A66597_HCD=y
CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_MMC=y
CONFIG_MMC_SPI=y
CONFIG_MMC_SDHI=y
diff --git a/arch/sh/configs/se7724_defconfig b/arch/sh/configs/se7724_defconfig
index ed35093..1faa788 100644
--- a/arch/sh/configs/se7724_defconfig
+++ b/arch/sh/configs/se7724_defconfig
@@ -109,7 +109,7 @@ CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_SPI=y
--
1.7.7.3
^ permalink raw reply related
* [PATCH 07/11] ARM: OMAP: Move omap-pm-noop.c local to mach-omap2
From: Tony Lindgren @ 2012-10-31 20:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121030235255.25936.36727.stgit@muffinssi.local>
* Tony Lindgren <tony@atomide.com> [121030 16:55]:
> This code should be private to mach-omap2.
>
> The only use for it in for omap1 has been in dmtimer.c
> to check for context loss. However, omap1 does not
> lose context during idle, so the code is not needed.
> Further, omap1 timer has OMAP_TIMER_ALWON set, so omap1
> was not hitting omap_pm_get_dev_context_loss_count()
> test.
Noticed one issue with my test compiles in the
omap-for-v3.8/cleanup-headers branch that can be
fixed along with this patch.
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -36,7 +36,6 @@
#include <media/v4l2-ioctl.h>
#include <plat/iommu.h>
#include <plat/iovmm.h>
-#include <plat/omap-pm.h>
#include "ispvideo.h"
#include "isp.h"
I'll fold that into this patch.
Regards,
Tony
> Cc: Jon Hunter <jon-hunter@ti.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
> arch/arm/mach-omap2/Makefile | 1 +
> arch/arm/mach-omap2/omap-pm-noop.c | 4 ++--
> arch/arm/mach-omap2/timer.c | 2 ++
> arch/arm/plat-omap/Makefile | 1 -
> arch/arm/plat-omap/dmtimer.c | 17 ++++++++++-------
> arch/arm/plat-omap/include/plat/dmtimer.h | 2 ++
> 6 files changed, 17 insertions(+), 10 deletions(-)
> rename arch/arm/{plat-omap/omap-pm-noop.c => mach-omap2/omap-pm-noop.c} (99%)
>
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index e3de5d4..b118ed5 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -70,6 +70,7 @@ obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o
> obj-$(CONFIG_ARCH_OMAP4) += sleep44xx.o
> obj-$(CONFIG_SOC_OMAP5) += omap-mpuss-lowpower.o sleep44xx.o
> obj-$(CONFIG_PM_DEBUG) += pm-debug.o
> +obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
>
> obj-$(CONFIG_POWER_AVS_OMAP) += sr_device.o
> obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) += smartreflex-class3.o
> diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/mach-omap2/omap-pm-noop.c
> similarity index 99%
> rename from arch/arm/plat-omap/omap-pm-noop.c
> rename to arch/arm/mach-omap2/omap-pm-noop.c
> index 198685b..6a3be2b 100644
> --- a/arch/arm/plat-omap/omap-pm-noop.c
> +++ b/arch/arm/mach-omap2/omap-pm-noop.c
> @@ -22,8 +22,8 @@
> #include <linux/device.h>
> #include <linux/platform_device.h>
>
> -#include "../mach-omap2/omap_device.h"
> -#include "../mach-omap2/omap-pm.h"
> +#include "omap_device.h"
> +#include "omap-pm.h"
>
> static bool off_mode_enabled;
> static int dummy_context_loss_counter;
> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> index 565e575..95e4478 100644
> --- a/arch/arm/mach-omap2/timer.c
> +++ b/arch/arm/mach-omap2/timer.c
> @@ -559,6 +559,8 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
> if (timer_dev_attr)
> pdata->timer_capability = timer_dev_attr->timer_capability;
>
> + pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
> +
> pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
> NULL, 0, 0);
>
> diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
> index 4bd0ace..50da9bf 100644
> --- a/arch/arm/plat-omap/Makefile
> +++ b/arch/arm/plat-omap/Makefile
> @@ -19,4 +19,3 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y)
> # OMAP mailbox framework
> obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
>
> -obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
> diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
> index 4a0b30a..9a0bbc4 100644
> --- a/arch/arm/plat-omap/dmtimer.c
> +++ b/arch/arm/plat-omap/dmtimer.c
> @@ -45,8 +45,6 @@
>
> #include <mach/hardware.h>
>
> -#include "../mach-omap2/omap-pm.h"
> -
> static u32 omap_reserved_systimers;
> static LIST_HEAD(omap_timer_list);
> static DEFINE_SPINLOCK(dm_timer_lock);
> @@ -349,7 +347,8 @@ int omap_dm_timer_start(struct omap_dm_timer *timer)
> omap_dm_timer_enable(timer);
>
> if (!(timer->capability & OMAP_TIMER_ALWON)) {
> - if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
> + if (timer->get_context_loss_count &&
> + timer->get_context_loss_count(&timer->pdev->dev) !=
> timer->ctx_loss_count)
> omap_timer_restore_context(timer);
> }
> @@ -378,9 +377,11 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)
>
> __omap_dm_timer_stop(timer, timer->posted, rate);
>
> - if (!(timer->capability & OMAP_TIMER_ALWON))
> - timer->ctx_loss_count =
> - omap_pm_get_dev_context_loss_count(&timer->pdev->dev);
> + if (!(timer->capability & OMAP_TIMER_ALWON)) {
> + if (timer->get_context_loss_count)
> + timer->ctx_loss_count =
> + timer->get_context_loss_count(&timer->pdev->dev);
> + }
>
> /*
> * Since the register values are computed and written within
> @@ -496,7 +497,8 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
> omap_dm_timer_enable(timer);
>
> if (!(timer->capability & OMAP_TIMER_ALWON)) {
> - if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
> + if (timer->get_context_loss_count &&
> + timer->get_context_loss_count(&timer->pdev->dev) !=
> timer->ctx_loss_count)
> omap_timer_restore_context(timer);
> }
> @@ -730,6 +732,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
> timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
> timer->pdev = pdev;
> timer->capability = pdata->timer_capability;
> + timer->get_context_loss_count = pdata->get_context_loss_count;
>
> /* Skip pm_runtime_enable for OMAP1 */
> if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
> diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
> index 85868e9..3f5b9cf 100644
> --- a/arch/arm/plat-omap/include/plat/dmtimer.h
> +++ b/arch/arm/plat-omap/include/plat/dmtimer.h
> @@ -94,6 +94,7 @@ struct dmtimer_platform_data {
> /* set_timer_src - Only used for OMAP1 devices */
> int (*set_timer_src)(struct platform_device *pdev, int source);
> u32 timer_capability;
> + int (*get_context_loss_count)(struct device *);
> };
>
> int omap_dm_timer_reserve_systimer(int id);
> @@ -263,6 +264,7 @@ struct omap_dm_timer {
> unsigned reserved:1;
> unsigned posted:1;
> struct timer_regs context;
> + int (*get_context_loss_count)(struct device *);
> int ctx_loss_count;
> int revision;
> u32 capability;
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* OMAP baseline test results for v3.7-rc1
From: Jean Pihet @ 2012-10-31 21:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87fw4u3oh5.fsf@deeprootsystems.com>
Hi Kevin,
On Wed, Oct 31, 2012 at 6:49 AM, Kevin Hilman
<khilman@deeprootsystems.com> wrote:
> Hi Jean,
>
> Jean Pihet <jean.pihet@newoldbits.com> writes:
>
> [...]
>
>>> Based on a very quick look, I'd say the original patch 3db11fe is broken.
>>> I don't see how it can ensure that its PM_QOS_CPU_DMA_LATENCY request is
>>> honored when CONFIG_CPU_IDLE=n. CONFIG_CPU_IDLE=n is the default for
>>> omap2plus_defconfig.
>>
>> Withtout CPU_IDLE set the PM QoS has no influence on the power domains states.
>
> Exactly, which means there is *no* constraint set when CPUidle is
> disabled,
Correct. With CPU_IDLE disabled PM QoS manages the constraints list
but cpuidle does not request the aggregated value nor does it restrict
the CPU and CORE power domains states.
> and it's exactly this that is different from the behavior
> before your patch.
No.
> Before your patch, the constraint would be set whether or not CPUidle
> was enabled, correct?
No. In the linux-omap source tree the OMAP PM API for the latency
constraints simply is a no-op. The only difference with the code after
the patch is that PM QoS manages the constraints list, which should be
neglictable in terms of CPU execution time.
Paul,
Could you please check with the 2 calls to PM QoS from the I2C code
commented out? This will rule out the PM QoS impact.
> The solution to this will probably be to make OMAPs non-CPUidle idle path
> check the constraints.
This is the idea behind the per-device PM QoS support, which allows to
set a constraint on any device and so on any power domain (note that
cpuidle influences CPU and CORE only).
However in the current context -the I2C timeouts issue- there is no
apparent link between the issue and the patch 3db11fef [1].
[1] http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=3db11feffc1ad2ab9dea27789e6b5b3032827adc
> Kevin
Thanks,
Jean
^ permalink raw reply
* [PATCH 11/11] ARM: OMAP1: Remove relative includes
From: Tony Lindgren @ 2012-10-31 21:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121030235306.25936.38688.stgit@muffinssi.local>
* Tony Lindgren <tony@atomide.com> [121030 16:55]:
> As discussed on linux-arm-kernel, we want to avoid
> relative includes for the arch/arm/*omap* code:
>
> http://www.spinics.net/lists/linux-omap/msg80520.html
>
> Note that eventually when the omap1 specific drivers
> are fixed to not use cpu_is_omap macros and not depend
> on mach/hardware.h, this patch can be reverted and these
> headers can be local. But since just fixing the drivers for
> omap2+ is already a big enough hassle, let's deal
> with that properly first.
Forgot to change plat/cpu.h in this patch, will fold it
into this patch as below.
Regards,
Tony
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -29,7 +29,7 @@
#define __ASM_ARCH_OMAP_CPU_H
#ifdef CONFIG_ARCH_OMAP1
-#include "../../mach-omap1/soc.h"
+#include <mach/soc.h>
#endif
#ifdef CONFIG_ARCH_OMAP2PLUS
^ permalink raw reply
* [PATCH V4 3/7] ARM: tegra30: cpuidle: add powered-down state for secondary CPUs
From: Colin Cross @ 2012-10-31 21:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351676481-28425-4-git-send-email-josephl@nvidia.com>
On Wed, Oct 31, 2012 at 2:41 AM, Joseph Lo <josephl@nvidia.com> wrote:
> This supports power-gated idle on secondary CPUs for Tegra30. The
> secondary CPUs can go into powered-down state independently. When
> CPU goes into this state, it saves it's contexts and puts itself
> to flow controlled WFI state. After that, it will been power gated.
>
> Be aware of that, you may see the legacy power state "LP2" in the
> code which is exactly the same meaning of "CPU power down".
On Tegra20, LP2 included powering off the GIC. Is that still the case
for Tegra30 individual secondary cpu power gating? If so, how do IPIs
to an idle cpu wake it up?
^ permalink raw reply
* [PATCH V4 REPOST] ARM: implement debug_ll_io_init()
From: Stephen Warren @ 2012-10-31 21:21 UTC (permalink / raw)
To: linux-arm-kernel
From: Rob Herring <rob.herring@calxeda.com>
When using DEBUG_LL, the UART's (or other HW's) registers are mapped
into early page tables based on the results of assembly macro addruart.
Later, when the page tables are replaced, the same virtual address must
remain valid. Historically, this has been ensured by using defines from
<mach/iomap.h> in both the implementation of addruart, and the machine's
.map_io() function. However, with the move to single zImage, we wish to
remove <mach/iomap.h>. To enable this, the macro addruart may be used
when constructing the late page tables too; addruart is exposed as a
C function debug_ll_addr(), and used to set up the required mapping in
debug_ll_io_init(), which may called on an opt-in basis from a machine's
.map_io() function.
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
[swarren: Mask map.virtual with PAGE_MASK. Checked for NULL results from
debug_ll_addr (e.g. when selected UART isn't valid). Fixed compile when
either !CONFIG_DEBUG_LL or CONFIG_DEBUG_SEMIHOSTING.]
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
Arnd, Olof, could this patch be placed into a standalone topic branch in
arm-soc branch; I'd like to make use of this patch for both Tegra and
bcm2835 this cycle, and perhaps others might too. Thanks.
v4: Fix DEBUG_SEMIHOSTING's debug_ll_addr to actually fill in the "out"
parameters.
v3: New patch.
---
arch/arm/include/asm/mach/map.h | 7 +++++++
arch/arm/kernel/debug.S | 14 ++++++++++++++
arch/arm/mm/mmu.c | 16 ++++++++++++++++
3 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index 195ac2f..2fe141f 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -40,6 +40,13 @@ extern void iotable_init(struct map_desc *, int);
extern void vm_reserve_area_early(unsigned long addr, unsigned long size,
void *caller);
+#ifdef CONFIG_DEBUG_LL
+extern void debug_ll_addr(unsigned long *paddr, unsigned long *vaddr);
+extern void debug_ll_io_init(void);
+#else
+static inline void debug_ll_io_init(void) {}
+#endif
+
struct mem_type;
extern const struct mem_type *get_mem_type(unsigned int type);
/*
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index 66f711b..6809200 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -100,6 +100,13 @@ ENTRY(printch)
b 1b
ENDPROC(printch)
+ENTRY(debug_ll_addr)
+ addruart r2, r3, ip
+ str r2, [r0]
+ str r3, [r1]
+ mov pc, lr
+ENDPROC(debug_ll_addr)
+
#else
ENTRY(printascii)
@@ -119,4 +126,11 @@ ENTRY(printch)
mov pc, lr
ENDPROC(printch)
+ENTRY(debug_ll_addr)
+ mov r2, #0
+ str r2, [r0]
+ str r2, [r1]
+ mov pc, lr
+ENDPROC(debug_ll_addr)
+
#endif
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index b675918..08d04fc 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -893,6 +893,22 @@ static void __init pci_reserve_io(void)
#define pci_reserve_io() do { } while (0)
#endif
+#ifdef CONFIG_DEBUG_LL
+void __init debug_ll_io_init(void)
+{
+ struct map_desc map;
+
+ debug_ll_addr(&map.pfn, &map.virtual);
+ if (!map.pfn || !map.virtual)
+ return;
+ map.pfn = __phys_to_pfn(map.pfn);
+ map.virtual &= PAGE_MASK;
+ map.length = PAGE_SIZE;
+ map.type = MT_DEVICE;
+ create_mapping(&map);
+}
+#endif
+
static void * __initdata vmalloc_min =
(void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET);
--
1.7.0.4
^ permalink raw reply related
* [PATCH] ARM: plat-versatile: move FPGA irq driver to drivers/irqchip
From: Linus Walleij @ 2012-10-31 21:31 UTC (permalink / raw)
To: linux-arm-kernel
This moves the Versatile FPGA interrupt controller driver, used in
the Integrator/AP, Integrator/CP and some Versatile boards, out
of arch/arm/plat-versatile and down to drivers/irqchip where we
have consensus that such drivers belong. The header file is
consequently moved to <linux/platform_data/irq-versatile-fpga.h>.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
arch/arm/Kconfig | 4 +-
arch/arm/mach-integrator/integrator_ap.c | 3 +-
arch/arm/mach-integrator/integrator_cp.c | 2 +-
arch/arm/mach-versatile/core.c | 2 +-
arch/arm/plat-versatile/Kconfig | 9 -
arch/arm/plat-versatile/Makefile | 1 -
drivers/irqchip/Kconfig | 9 +-
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-arm-fpga.c | 204 +++++++++++++++++++++
.../irqchip/irq-versatile-fpga.c | 4 +-
.../linux/platform_data/irq-versatile-fpga.h | 0
11 files changed, 220 insertions(+), 19 deletions(-)
create mode 100644 drivers/irqchip/irq-arm-fpga.c
rename arch/arm/plat-versatile/fpga-irq.c => drivers/irqchip/irq-versatile-fpga.c (97%)
rename arch/arm/plat-versatile/include/plat/fpga-irq.h => include/linux/platform_data/irq-versatile-fpga.h (100%)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 73067ef..2205e3e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -284,8 +284,8 @@ config ARCH_INTEGRATOR
select MULTI_IRQ_HANDLER
select NEED_MACH_MEMORY_H
select PLAT_VERSATILE
- select PLAT_VERSATILE_FPGA_IRQ
select SPARSE_IRQ
+ select VERSATILE_FPGA_IRQ
help
Support for ARM's Integrator platform.
@@ -318,7 +318,7 @@ config ARCH_VERSATILE
select PLAT_VERSATILE
select PLAT_VERSATILE_CLCD
select PLAT_VERSATILE_CLOCK
- select PLAT_VERSATILE_FPGA_IRQ
+ select VERSATILE_FPGA_IRQ
help
This enables support for ARM Ltd Versatile board.
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 4f13bc5..caa279f 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -34,6 +34,7 @@
#include <linux/mtd/physmap.h>
#include <linux/clk.h>
#include <linux/platform_data/clk-integrator.h>
+#include <linux/platform_data/irq-versatile-fpga.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
@@ -56,8 +57,6 @@
#include <asm/mach/pci.h>
#include <asm/mach/time.h>
-#include <plat/fpga-irq.h>
-
#include "common.h"
/*
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 4423bc8..b50fdc7 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -23,6 +23,7 @@
#include <linux/gfp.h>
#include <linux/mtd/physmap.h>
#include <linux/platform_data/clk-integrator.h>
+#include <linux/platform_data/irq-versatile-fpga.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
@@ -46,7 +47,6 @@
#include <asm/hardware/timer-sp.h>
#include <plat/clcd.h>
-#include <plat/fpga-irq.h>
#include <plat/sched_clock.h>
#include "common.h"
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 5b5c1ee..46bfb8c 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -35,6 +35,7 @@
#include <linux/gfp.h>
#include <linux/clkdev.h>
#include <linux/mtd/physmap.h>
+#include <linux/platform_data/irq-versatile-fpga.h>
#include <asm/irq.h>
#include <asm/hardware/arm_timer.h>
@@ -51,7 +52,6 @@
#include <asm/hardware/timer-sp.h>
#include <plat/clcd.h>
-#include <plat/fpga-irq.h>
#include <plat/sched_clock.h>
#include "core.h"
diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig
index 2a4ae8a..619f0fa 100644
--- a/arch/arm/plat-versatile/Kconfig
+++ b/arch/arm/plat-versatile/Kconfig
@@ -6,15 +6,6 @@ config PLAT_VERSATILE_CLOCK
config PLAT_VERSATILE_CLCD
bool
-config PLAT_VERSATILE_FPGA_IRQ
- bool
- select IRQ_DOMAIN
-
-config PLAT_VERSATILE_FPGA_IRQ_NR
- int
- default 4
- depends on PLAT_VERSATILE_FPGA_IRQ
-
config PLAT_VERSATILE_LEDS
def_bool y if NEW_LEDS
depends on ARCH_REALVIEW || ARCH_VERSATILE
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile
index 74cfd94..f88d448 100644
--- a/arch/arm/plat-versatile/Makefile
+++ b/arch/arm/plat-versatile/Makefile
@@ -2,7 +2,6 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o
obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
-obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 1bb8bf6..62ca575 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -1 +1,8 @@
-# empty
+config VERSATILE_FPGA_IRQ
+ bool
+ select IRQ_DOMAIN
+
+config VERSATILE_FPGA_IRQ_NR
+ int
+ default 4
+ depends on VERSATILE_FPGA_IRQ
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 054321d..e2e6eb5 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
+obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
diff --git a/drivers/irqchip/irq-arm-fpga.c b/drivers/irqchip/irq-arm-fpga.c
new file mode 100644
index 0000000..92fb9d6
--- /dev/null
+++ b/drivers/irqchip/irq-arm-fpga.c
@@ -0,0 +1,204 @@
+/*
+ * Support for Versatile FPGA-based IRQ controllers
+ */
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_data/irq-versatile-fpga.h>
+
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#define IRQ_STATUS 0x00
+#define IRQ_RAW_STATUS 0x04
+#define IRQ_ENABLE_SET 0x08
+#define IRQ_ENABLE_CLEAR 0x0c
+#define INT_SOFT_SET 0x10
+#define INT_SOFT_CLEAR 0x14
+#define FIQ_STATUS 0x20
+#define FIQ_RAW_STATUS 0x24
+#define FIQ_ENABLE 0x28
+#define FIQ_ENABLE_SET 0x28
+#define FIQ_ENABLE_CLEAR 0x2C
+
+/**
+ * struct fpga_irq_data - irq data container for the FPGA IRQ controller
+ * @base: memory offset in virtual memory
+ * @chip: chip container for this instance
+ * @domain: IRQ domain for this instance
+ * @valid: mask for valid IRQs on this controller
+ * @used_irqs: number of active IRQs on this controller
+ */
+struct fpga_irq_data {
+ void __iomem *base;
+ struct irq_chip chip;
+ u32 valid;
+ struct irq_domain *domain;
+ u8 used_irqs;
+};
+
+/* we cannot allocate memory when the controllers are initially registered */
+static struct fpga_irq_data fpga_irq_devices[CONFIG_VERSATILE_FPGA_IRQ_NR];
+static int fpga_irq_id;
+
+static void fpga_irq_mask(struct irq_data *d)
+{
+ struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
+ u32 mask = 1 << d->hwirq;
+
+ writel(mask, f->base + IRQ_ENABLE_CLEAR);
+}
+
+static void fpga_irq_unmask(struct irq_data *d)
+{
+ struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
+ u32 mask = 1 << d->hwirq;
+
+ writel(mask, f->base + IRQ_ENABLE_SET);
+}
+
+static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc)
+{
+ struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
+ u32 status = readl(f->base + IRQ_STATUS);
+
+ if (status == 0) {
+ do_bad_IRQ(irq, desc);
+ return;
+ }
+
+ do {
+ irq = ffs(status) - 1;
+ status &= ~(1 << irq);
+ generic_handle_irq(irq_find_mapping(f->domain, irq));
+ } while (status);
+}
+
+/*
+ * Handle each interrupt in a single FPGA IRQ controller. Returns non-zero
+ * if we've handled at least one interrupt. This does a single read of the
+ * status register and handles all interrupts in order from LSB first.
+ */
+static int handle_one_fpga(struct fpga_irq_data *f, struct pt_regs *regs)
+{
+ int handled = 0;
+ int irq;
+ u32 status;
+
+ while ((status = readl(f->base + IRQ_STATUS))) {
+ irq = ffs(status) - 1;
+ handle_IRQ(irq_find_mapping(f->domain, irq), regs);
+ handled = 1;
+ }
+
+ return handled;
+}
+
+/*
+ * Keep iterating over all registered FPGA IRQ controllers until there are
+ * no pending interrupts.
+ */
+asmlinkage void __exception_irq_entry fpga_handle_irq(struct pt_regs *regs)
+{
+ int i, handled;
+
+ do {
+ for (i = 0, handled = 0; i < fpga_irq_id; ++i)
+ handled |= handle_one_fpga(&fpga_irq_devices[i], regs);
+ } while (handled);
+}
+
+static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct fpga_irq_data *f = d->host_data;
+
+ /* Skip invalid IRQs, only register handlers for the real ones */
+ if (!(f->valid & BIT(hwirq)))
+ return -ENOTSUPP;
+ irq_set_chip_data(irq, f);
+ irq_set_chip_and_handler(irq, &f->chip,
+ handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ return 0;
+}
+
+static struct irq_domain_ops fpga_irqdomain_ops = {
+ .map = fpga_irqdomain_map,
+ .xlate = irq_domain_xlate_onetwocell,
+};
+
+void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
+ int parent_irq, u32 valid, struct device_node *node)
+{
+ struct fpga_irq_data *f;
+ int i;
+
+ if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) {
+ pr_err("%s: too few FPGA IRQ controllers, increase CONFIG_VERSATILE_FPGA_IRQ_NR\n", __func__);
+ return;
+ }
+ f = &fpga_irq_devices[fpga_irq_id];
+ f->base = base;
+ f->chip.name = name;
+ f->chip.irq_ack = fpga_irq_mask;
+ f->chip.irq_mask = fpga_irq_mask;
+ f->chip.irq_unmask = fpga_irq_unmask;
+ f->valid = valid;
+
+ if (parent_irq != -1) {
+ irq_set_handler_data(parent_irq, f);
+ irq_set_chained_handler(parent_irq, fpga_irq_handle);
+ }
+
+ /* This will also allocate irq descriptors */
+ f->domain = irq_domain_add_simple(node, fls(valid), irq_start,
+ &fpga_irqdomain_ops, f);
+
+ /* This will allocate all valid descriptors in the linear case */
+ for (i = 0; i < fls(valid); i++)
+ if (valid & BIT(i)) {
+ if (!irq_start)
+ irq_create_mapping(f->domain, i);
+ f->used_irqs++;
+ }
+
+ pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
+ fpga_irq_id, name, base, f->used_irqs);
+
+ fpga_irq_id++;
+}
+
+#ifdef CONFIG_OF
+int __init fpga_irq_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct fpga_irq_data *f;
+ void __iomem *base;
+ u32 clear_mask;
+ u32 valid_mask;
+
+ if (WARN_ON(!node))
+ return -ENODEV;
+
+ base = of_iomap(node, 0);
+ WARN(!base, "unable to map fpga irq registers\n");
+
+ if (of_property_read_u32(node, "clear-mask", &clear_mask))
+ clear_mask = 0;
+
+ if (of_property_read_u32(node, "valid-mask", &valid_mask))
+ valid_mask = 0;
+
+ fpga_irq_init(base, node->name, 0, -1, valid_mask, node);
+
+ writel(clear_mask, base + IRQ_ENABLE_CLEAR);
+ writel(clear_mask, base + FIQ_ENABLE_CLEAR);
+
+ return 0;
+}
+#endif
diff --git a/arch/arm/plat-versatile/fpga-irq.c b/drivers/irqchip/irq-versatile-fpga.c
similarity index 97%
rename from arch/arm/plat-versatile/fpga-irq.c
rename to drivers/irqchip/irq-versatile-fpga.c
index dfe317c..b7aab6e 100644
--- a/arch/arm/plat-versatile/fpga-irq.c
+++ b/drivers/irqchip/irq-versatile-fpga.c
@@ -8,10 +8,10 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/platform_data/irq-versatile-fpga.h>
#include <asm/exception.h>
#include <asm/mach/irq.h>
-#include <plat/fpga-irq.h>
#define IRQ_STATUS 0x00
#define IRQ_RAW_STATUS 0x04
@@ -42,7 +42,7 @@ struct fpga_irq_data {
};
/* we cannot allocate memory when the controllers are initially registered */
-static struct fpga_irq_data fpga_irq_devices[CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR];
+static struct fpga_irq_data fpga_irq_devices[CONFIG_VERSATILE_FPGA_IRQ_NR];
static int fpga_irq_id;
static void fpga_irq_mask(struct irq_data *d)
diff --git a/arch/arm/plat-versatile/include/plat/fpga-irq.h b/include/linux/platform_data/irq-versatile-fpga.h
similarity index 100%
rename from arch/arm/plat-versatile/include/plat/fpga-irq.h
rename to include/linux/platform_data/irq-versatile-fpga.h
--
1.7.11.7
^ permalink raw reply related
* [PATCH 12/11] ARM: OMAP: Fix relative includes for fpga.h
From: Tony Lindgren @ 2012-10-31 21:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121030234852.25936.12482.stgit@muffinssi.local>
As discussed on linux-arm-kernel, we want to avoid
relative includes for the arch/arm/*omap* code:
http://www.spinics.net/lists/linux-omap/msg80520.html
Fix includes for fpga.h by making fpga.h local
to mach-omap1. The common code in plat-omap just
needs to know the struct h2p2_dbg_fpga, which can
be local to debug-leds.c.
This also fixes the braindead <../*.h> style includes
that got accidentally added with search and replace
during the cleanup.
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
Looks like my grepping missed few totally braindead
includes I accidentally introduced, posting them as
additional patches to this series.
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 8b5800a..e067f22 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -30,13 +30,13 @@
#include <mach/tc.h>
#include <mach/mux.h>
#include <mach/flash.h>
-#include <../plat-omap/fpga.h>
#include <linux/platform_data/keypad-omap.h>
#include <mach/hardware.h>
#include "iomap.h"
#include "common.h"
+#include "fpga.h"
/* fsample is pretty close to p2-sample */
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index c66334f..f8033fa 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -33,7 +33,6 @@
#include <mach/mux.h>
#include <mach/flash.h>
-#include <../plat-omap/fpga.h>
#include <mach/tc.h>
#include <linux/platform_data/keypad-omap.h>
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 030bd48..9a7e483 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -30,13 +30,13 @@
#include <mach/tc.h>
#include <mach/mux.h>
-#include <../plat-omap/fpga.h>
#include <mach/flash.h>
#include <mach/hardware.h>
#include "iomap.h"
#include "common.h"
+#include "fpga.h"
static const unsigned int p2_keymap[] = {
KEY(0, 0, KEY_UP),
diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c
index d940fac..8bd71b2 100644
--- a/arch/arm/mach-omap1/fpga.c
+++ b/arch/arm/mach-omap1/fpga.c
@@ -27,12 +27,11 @@
#include <asm/irq.h>
#include <asm/mach/irq.h>
-#include <../plat-omap/fpga.h>
-
#include <mach/hardware.h>
#include "iomap.h"
#include "common.h"
+#include "fpga.h"
static void fpga_mask_irq(struct irq_data *d)
{
diff --git a/arch/arm/mach-omap1/fpga.h b/arch/arm/mach-omap1/fpga.h
new file mode 100644
index 0000000..4b4307a
--- /dev/null
+++ b/arch/arm/mach-omap1/fpga.h
@@ -0,0 +1,52 @@
+/*
+ * Interrupt handler for OMAP-1510 FPGA
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ *
+ * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6
+ * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_OMAP_FPGA_H
+#define __ASM_ARCH_OMAP_FPGA_H
+
+/*
+ * ---------------------------------------------------------------------------
+ * H2/P2 Debug board FPGA
+ * ---------------------------------------------------------------------------
+ */
+/* maps in the FPGA registers and the ETHR registers */
+#define H2P2_DBG_FPGA_BASE 0xE8000000 /* VA */
+#define H2P2_DBG_FPGA_SIZE SZ_4K /* SIZE */
+#define H2P2_DBG_FPGA_START 0x04000000 /* PA */
+
+#define H2P2_DBG_FPGA_ETHR_START (H2P2_DBG_FPGA_START + 0x300)
+#define H2P2_DBG_FPGA_FPGA_REV IOMEM(H2P2_DBG_FPGA_BASE + 0x10) /* FPGA Revision */
+#define H2P2_DBG_FPGA_BOARD_REV IOMEM(H2P2_DBG_FPGA_BASE + 0x12) /* Board Revision */
+#define H2P2_DBG_FPGA_GPIO IOMEM(H2P2_DBG_FPGA_BASE + 0x14) /* GPIO outputs */
+#define H2P2_DBG_FPGA_LEDS IOMEM(H2P2_DBG_FPGA_BASE + 0x16) /* LEDs outputs */
+#define H2P2_DBG_FPGA_MISC_INPUTS IOMEM(H2P2_DBG_FPGA_BASE + 0x18) /* Misc inputs */
+#define H2P2_DBG_FPGA_LAN_STATUS IOMEM(H2P2_DBG_FPGA_BASE + 0x1A) /* LAN Status line */
+#define H2P2_DBG_FPGA_LAN_RESET IOMEM(H2P2_DBG_FPGA_BASE + 0x1C) /* LAN Reset line */
+
+/* LEDs definition on debug board (16 LEDs, all physically green) */
+#define H2P2_DBG_FPGA_LED_GREEN (1 << 15)
+#define H2P2_DBG_FPGA_LED_AMBER (1 << 14)
+#define H2P2_DBG_FPGA_LED_RED (1 << 13)
+#define H2P2_DBG_FPGA_LED_BLUE (1 << 12)
+/* cpu0 load-meter LEDs */
+#define H2P2_DBG_FPGA_LOAD_METER (1 << 0) // A bit of fun on our board ...
+#define H2P2_DBG_FPGA_LOAD_METER_SIZE 11
+#define H2P2_DBG_FPGA_LOAD_METER_MASK ((1 << H2P2_DBG_FPGA_LOAD_METER_SIZE) - 1)
+
+#define H2P2_DBG_FPGA_P2_LED_TIMER (1 << 0)
+#define H2P2_DBG_FPGA_P2_LED_IDLE (1 << 1)
+
+#endif
diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c
index feca128..c43ea21 100644
--- a/arch/arm/plat-omap/debug-leds.c
+++ b/arch/arm/plat-omap/debug-leds.c
@@ -17,16 +17,33 @@
#include <linux/platform_data/gpio-omap.h>
#include <linux/slab.h>
-#include <mach/hardware.h>
#include <asm/mach-types.h>
-#include "fpga.h"
-
/* Many OMAP development platforms reuse the same "debug board"; these
* platforms include H2, H3, H4, and Perseus2. There are 16 LEDs on the
* debug board (all green), accessed through FPGA registers.
*/
+/* NOTE: most boards don't have a static mapping for the FPGA ... */
+struct h2p2_dbg_fpga {
+ /* offset 0x00 */
+ u16 smc91x[8];
+ /* offset 0x10 */
+ u16 fpga_rev;
+ u16 board_rev;
+ u16 gpio_outputs;
+ u16 leds;
+ /* offset 0x18 */
+ u16 misc_inputs;
+ u16 lan_status;
+ u16 lan_reset;
+ u16 reserved0;
+ /* offset 0x20 */
+ u16 ps2_data;
+ u16 ps2_ctrl;
+ /* plus also 4 rs232 ports ... */
+};
+
static struct h2p2_dbg_fpga __iomem *fpga;
static u16 fpga_led_state;
diff --git a/arch/arm/plat-omap/fpga.h b/arch/arm/plat-omap/fpga.h
deleted file mode 100644
index 54faaa9..0000000
--- a/arch/arm/plat-omap/fpga.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/fpga.h
- *
- * Interrupt handler for OMAP-1510 FPGA
- *
- * Copyright (C) 2001 RidgeRun, Inc.
- * Author: Greg Lonnon <glonnon@ridgerun.com>
- *
- * Copyright (C) 2002 MontaVista Software, Inc.
- *
- * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6
- * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_OMAP_FPGA_H
-#define __ASM_ARCH_OMAP_FPGA_H
-
-/*
- * ---------------------------------------------------------------------------
- * H2/P2 Debug board FPGA
- * ---------------------------------------------------------------------------
- */
-/* maps in the FPGA registers and the ETHR registers */
-#define H2P2_DBG_FPGA_BASE 0xE8000000 /* VA */
-#define H2P2_DBG_FPGA_SIZE SZ_4K /* SIZE */
-#define H2P2_DBG_FPGA_START 0x04000000 /* PA */
-
-#define H2P2_DBG_FPGA_ETHR_START (H2P2_DBG_FPGA_START + 0x300)
-#define H2P2_DBG_FPGA_FPGA_REV IOMEM(H2P2_DBG_FPGA_BASE + 0x10) /* FPGA Revision */
-#define H2P2_DBG_FPGA_BOARD_REV IOMEM(H2P2_DBG_FPGA_BASE + 0x12) /* Board Revision */
-#define H2P2_DBG_FPGA_GPIO IOMEM(H2P2_DBG_FPGA_BASE + 0x14) /* GPIO outputs */
-#define H2P2_DBG_FPGA_LEDS IOMEM(H2P2_DBG_FPGA_BASE + 0x16) /* LEDs outputs */
-#define H2P2_DBG_FPGA_MISC_INPUTS IOMEM(H2P2_DBG_FPGA_BASE + 0x18) /* Misc inputs */
-#define H2P2_DBG_FPGA_LAN_STATUS IOMEM(H2P2_DBG_FPGA_BASE + 0x1A) /* LAN Status line */
-#define H2P2_DBG_FPGA_LAN_RESET IOMEM(H2P2_DBG_FPGA_BASE + 0x1C) /* LAN Reset line */
-
-/* NOTE: most boards don't have a static mapping for the FPGA ... */
-struct h2p2_dbg_fpga {
- /* offset 0x00 */
- u16 smc91x[8];
- /* offset 0x10 */
- u16 fpga_rev;
- u16 board_rev;
- u16 gpio_outputs;
- u16 leds;
- /* offset 0x18 */
- u16 misc_inputs;
- u16 lan_status;
- u16 lan_reset;
- u16 reserved0;
- /* offset 0x20 */
- u16 ps2_data;
- u16 ps2_ctrl;
- /* plus also 4 rs232 ports ... */
-};
-
-/* LEDs definition on debug board (16 LEDs, all physically green) */
-#define H2P2_DBG_FPGA_LED_GREEN (1 << 15)
-#define H2P2_DBG_FPGA_LED_AMBER (1 << 14)
-#define H2P2_DBG_FPGA_LED_RED (1 << 13)
-#define H2P2_DBG_FPGA_LED_BLUE (1 << 12)
-/* cpu0 load-meter LEDs */
-#define H2P2_DBG_FPGA_LOAD_METER (1 << 0) // A bit of fun on our board ...
-#define H2P2_DBG_FPGA_LOAD_METER_SIZE 11
-#define H2P2_DBG_FPGA_LOAD_METER_MASK ((1 << H2P2_DBG_FPGA_LOAD_METER_SIZE) - 1)
-
-#define H2P2_DBG_FPGA_P2_LED_TIMER (1 << 0)
-#define H2P2_DBG_FPGA_P2_LED_IDLE (1 << 1)
-
-#endif
^ permalink raw reply related
* [RFC 1/7] capebus: Core capebus support
From: Russ Dill @ 2012-10-31 21:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351702333-8456-2-git-send-email-panto@antoniou-consulting.com>
On Wed, Oct 31, 2012 at 9:52 AM, Pantelis Antoniou
<panto@antoniou-consulting.com> wrote:
> Introducing capebus; a bus that allows small boards (capes) to connect
> to a complex SoC using simple expansion connectors.
>
> Up to now to support these kind of boards, one had to hack the board files,
> and do all sort of gymnastics to handle all the different cases of
> conflict resolution.
>
> Capebus provides abstractions that keep the pain to a minimum.
>
> This part of the series is introducing the core capebus functionality
> dealing with the basic bus & driver probe functions.
>
> Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
> ---
> drivers/Kconfig | 2 +
> drivers/Makefile | 3 +
> drivers/capebus/Kconfig | 17 ++
> drivers/capebus/Makefile | 8 +
> drivers/capebus/capebus-driver.c | 608 +++++++++++++++++++++++++++++++++++++++
> drivers/capebus/capebus-probe.c | 320 +++++++++++++++++++++
> drivers/capebus/capebus-sysfs.c | 52 ++++
> include/linux/capebus.h | 298 +++++++++++++++++++
> 8 files changed, 1308 insertions(+)
> create mode 100644 drivers/capebus/Kconfig
> create mode 100644 drivers/capebus/Makefile
> create mode 100644 drivers/capebus/capebus-driver.c
> create mode 100644 drivers/capebus/capebus-probe.c
> create mode 100644 drivers/capebus/capebus-sysfs.c
> create mode 100644 include/linux/capebus.h
>
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index dbdefa3..bfbe1d1 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -156,4 +156,6 @@ source "drivers/pwm/Kconfig"
>
> source "drivers/irqchip/Kconfig"
>
> +source "drivers/capebus/Kconfig"
> +
> endmenu
> diff --git a/drivers/Makefile b/drivers/Makefile
> index a16a8d0..d7a103b 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -145,3 +145,6 @@ obj-$(CONFIG_EXTCON) += extcon/
> obj-$(CONFIG_MEMORY) += memory/
> obj-$(CONFIG_IIO) += iio/
> obj-$(CONFIG_VME_BUS) += vme/
> +
> +# Capebus
> +obj-$(CONFIG_CAPEBUS) += capebus/
> diff --git a/drivers/capebus/Kconfig b/drivers/capebus/Kconfig
> new file mode 100644
> index 0000000..cea1b68
> --- /dev/null
> +++ b/drivers/capebus/Kconfig
> @@ -0,0 +1,17 @@
> +#
> +# Capebus core support
> +#
> +
> +menu "CAPEBUS support"
> +
> +config CAPEBUS
> + bool "Capebus support"
> + default n
> + help
> + Enable to support capebus devices.
> +
> +source "drivers/capebus/boards/Kconfig"
> +
> +source "drivers/capebus/capes/Kconfig"
> +
> +endmenu
> diff --git a/drivers/capebus/Makefile b/drivers/capebus/Makefile
> new file mode 100644
> index 0000000..45aa303
> --- /dev/null
> +++ b/drivers/capebus/Makefile
> @@ -0,0 +1,8 @@
> +#
> +# Makefile for CAPEBUS devices
> +#
> +
> +obj-$(CONFIG_CAPEBUS) += capebus-probe.o \
> + capebus-driver.o capebus-sysfs.o
> +obj-$(CONFIG_CAPEBUS) += boards/
> +obj-$(CONFIG_CAPEBUS) += capes/
> diff --git a/drivers/capebus/capebus-driver.c b/drivers/capebus/capebus-driver.c
> new file mode 100644
> index 0000000..82b1d1b
> --- /dev/null
> +++ b/drivers/capebus/capebus-driver.c
> @@ -0,0 +1,608 @@
> +/*
> + * Capebus driver infrastructure
> + *
> + * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
> + * Copyright (C) 2012 Texas Instruments Inc.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/device.h>
> +#include <linux/mempolicy.h>
> +#include <linux/string.h>
> +#include <linux/slab.h>
> +#include <linux/cpu.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/suspend.h>
> +
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +
> +#include <linux/capebus.h>
> +
> +/**
> + * capebus_match_device - Tell if a cape device structure has a
> + * matching cape device id structure
> + * @drv: the cape driver to match against
> + * @dev: the cape device structure to match against
> + *
> + * Used by a driver to check whether a cape device present in the
> + * system is in its list of supported devices. Returns the matching
> + * cape_device_id structure or %NULL if there is no match.
> + */
> +static const struct cape_device_id *capebus_match_device(
> + struct cape_driver *drv, struct cape_dev *dev)
> +{
> + struct cape_bus *bus = dev->bus;
> + struct cape_slot *slot = dev->slot;
> +
> + BUG_ON(bus == NULL);
> + BUG_ON(slot == NULL);
> + BUG_ON(bus->ops == NULL);
> + BUG_ON(bus->ops->get_dev_id == NULL);
> +
> + return bus->ops->get_dev_id(slot);
> +}
> +
> +/**
> + * capebus_device_probe - check if a driver wants to claim a
> + * specific cape device
> + * @dev: cape device being probed
> + *
> + * returns 0 on success, else error.
> + * side-effect: cape_dev->driver is set to drv when drv claims cape_dev.
> + */
> +static int capebus_device_probe(struct device *dev)
> +{
> + const struct cape_device_id *id;
> + int error = 0;
> + struct cape_driver *drv;
> + struct cape_dev *cape_dev;
> + struct device *parent;
> +
> + drv = to_cape_driver(dev->driver);
> + cape_dev = to_cape_dev(dev);
> + cape_dev = capebus_dev_get(cape_dev);
> +
> + /* sanity checks */
> + if (cape_dev == NULL ||
> + cape_dev->bus == NULL || cape_dev->bus->ops == NULL ||
> + cape_dev->driver != NULL || drv->probe == NULL) {
> + error = -EINVAL;
> + goto err_no_sanity;
> + }
> +
> + id = capebus_match_device(drv, cape_dev);
> + if (!id) {
> + error = -ENODEV;
> + goto err_no_match;
> + }
> +
> + /* The parent device must be in active state when probing */
> + parent = cape_dev->dev.parent;
> + if (parent)
> + pm_runtime_get_sync(parent);
> +
> + /* Unbound cape devices are always set to disabled and suspended.
> + * During probe, the device is set to enabled and active and the
> + * usage count is incremented. If the driver supports runtime PM,
> + * it should call pm_runtime_put_noidle() in its probe routine and
> + * pm_runtime_get_noresume() in its remove routine.
> + */
> + pm_runtime_get_noresume(&cape_dev->dev);
> + pm_runtime_set_active(&cape_dev->dev);
> + pm_runtime_enable(&cape_dev->dev);
> +
> + /* call the driver's probe method */
> + error = drv->probe(cape_dev, id);
> +
> + /* release the parent no matter what */
> + if (parent)
> + pm_runtime_put(parent);
> +
> + if (error != 0)
> + goto err_probe_fail;
> +
> + /* call the probed bus method */
> + if (cape_dev->bus->ops->dev_probed != NULL) {
> + error = cape_dev->bus->ops->dev_probed(cape_dev);
> + if (error != 0)
> + goto err_dev_probed_fail;
> + }
> +
> + /* all is fine... */
> + cape_dev->driver = drv;
> + cape_dev->added = 1;
> +
> + return 0;
> +
> +err_dev_probed_fail:
> + if (drv->remove) {
> + pm_runtime_get_sync(&cape_dev->dev);
> + drv->remove(cape_dev);
> + pm_runtime_put_noidle(&cape_dev->dev);
> + }
> +err_probe_fail:
> + pm_runtime_disable(&cape_dev->dev);
> + pm_runtime_set_suspended(&cape_dev->dev);
> + pm_runtime_put_noidle(&cape_dev->dev);
> +err_no_match:
> + /* nothing */
> +err_no_sanity:
> + capebus_dev_put(cape_dev);
> + return error;
> +}
> +
> +static int capebus_device_remove(struct device *dev)
> +{
> + struct cape_dev *cape_dev = to_cape_dev(dev);
> + struct cape_driver *drv = cape_dev->driver;
> +
> + if (drv) {
> + /* call the removed bus method (if added prev.) */
> + if (cape_dev->added) {
> + BUG_ON(cape_dev->bus == NULL);
> + BUG_ON(cape_dev->bus->ops == NULL);
> + if (cape_dev->bus->ops->dev_removed)
> + cape_dev->bus->ops->dev_removed(cape_dev);
> + cape_dev->added = 0;
> + }
Is there any case where added will not track drv?
> + if (drv->remove) {
> + pm_runtime_get_sync(dev);
> + drv->remove(cape_dev);
> + pm_runtime_put_noidle(dev);
> + }
> + cape_dev->driver = NULL;
> + }
> +
> + /* Undo the runtime PM settings in local_capebus_probe() */
> + pm_runtime_disable(dev);
> + pm_runtime_set_suspended(dev);
> + pm_runtime_put_noidle(dev);
> +
> + capebus_dev_put(cape_dev);
> + return 0;
> +}
> +
> +static void capebus_device_shutdown(struct device *dev)
> +{
> + struct cape_dev *cape_dev = to_cape_dev(dev);
> + struct cape_driver *drv = cape_dev->driver;
> +
> + if (drv && drv->shutdown)
> + drv->shutdown(cape_dev);
> +
> + capebus_disable_device(cape_dev);
> +
> + if (!device_may_wakeup(dev))
> + capebus_enable_wake(cape_dev, false);
> +}
> +
> +static int capebus_bus_match(struct device *dev, struct device_driver *drv);
> +static int capebus_device_probe(struct device *dev);
> +static int capebus_device_remove(struct device *dev);
> +static void capebus_device_shutdown(struct device *dev);
> +
> +struct bus_type capebus_bus_type = {
> + .name = "capebus",
> + .match = capebus_bus_match,
> + .probe = capebus_device_probe,
> + .remove = capebus_device_remove,
> + .shutdown = capebus_device_shutdown,
> + .dev_attrs = capebus_dev_attrs,
> + .bus_attrs = capebus_bus_attrs,
> + .pm = NULL, /* No PM for now */
> +};
> +EXPORT_SYMBOL(capebus_bus_type);
> +
> +/**
> + * __capebus_register_driver - register a new capebus driver
> + * @drv: the driver structure to register
> + * @owner: owner module of drv
> + * @mod_name: module name string
> + *
> + * Adds the driver structure to the list of registered drivers.
> + * Returns a negative value on error, otherwise 0.
> + * If no error occurred, the driver remains registered even if
> + * no device was claimed during registration.
> + */
> +int __capebus_register_driver(struct cape_driver *drv, struct module *owner,
> + const char *mod_name)
> +{
> + /* initialize common driver fields */
> + drv->driver.bus = &capebus_bus_type;
> + drv->driver.owner = owner;
> + drv->driver.mod_name = mod_name;
> +
> + /* register with core */
> + return driver_register(&drv->driver);
> +}
> +EXPORT_SYMBOL(__capebus_register_driver);
> +
> +/**
> + * capebus_unregister_driver - unregister a capebus driver
> + * @drv: the driver structure to unregister
> + *
> + * Deletes the driver structure from the list of registered cape drivers,
> + * gives it a chance to clean up by calling its remove() function for
> + * each device it was responsible for, and marks those devices as
> + * driverless.
> + */
> +
> +void
> +capebus_unregister_driver(struct cape_driver *drv)
> +{
> + /* TODO: not really working properly */
> + driver_unregister(&drv->driver);
> +}
> +EXPORT_SYMBOL(capebus_unregister_driver);
> +
> +/**
> + * capebus_bus_match - Tell if a cape device structure has a matching
> + * cape device id structure
> + * @dev: the cape device structure to match against
> + * @drv: the device driver to search for matching cape device id structures
> + *
> + * Used by a driver to check whether a cape device present in the
> + * system is in its list of supported devices. Returns the matching
> + * cape_device_id structure or %NULL if there is no match.
> + */
> +static int capebus_bus_match(struct device *dev, struct device_driver *drv)
> +{
> + struct cape_dev *cape_dev = to_cape_dev(dev);
> + struct cape_driver *cape_drv = to_cape_driver(drv);
> + const struct cape_device_id *found_id;
> +
> + found_id = capebus_match_device(cape_drv, cape_dev);
> + if (found_id)
> + return 1;
> +
> + return 0;
> +}
> +
> +/**
> + * capebus_dev_get - increments the reference count of the capebus
> + * device structure
> + * @dev: the device being referenced
> + *
> + * Each live reference to a device should be refcounted.
> + *
> + * Drivers for cape devices should normally record such references in
> + * their probe() methods, when they bind to a device, and release
> + * them by calling capebus_dev_put(), in their disconnect() methods.
> + *
> + * A pointer to the device with the incremented reference counter is returned.
> + */
> +struct cape_dev *capebus_dev_get(struct cape_dev *dev)
> +{
> + if (dev)
> + get_device(&dev->dev);
> + return dev;
> +}
> +EXPORT_SYMBOL(capebus_dev_get);
> +
> +/**
> + * capebus_dev_put - release a use of the capebus device structure
> + * @dev: device that's been disconnected
> + *
> + * Must be called when a user of a device is finished with it. When the last
> + * user of the device calls this function, the memory of the device is freed.
> + */
> +void capebus_dev_put(struct cape_dev *dev)
> +{
> + if (dev)
> + put_device(&dev->dev);
> +}
> +EXPORT_SYMBOL(capebus_dev_put);
> +
> +static int __init capebus_driver_init(void)
> +{
> + return bus_register(&capebus_bus_type);
> +}
> +
> +postcore_initcall(capebus_driver_init);
> +
> +const struct of_device_id *
> +capebus_of_match_device(struct cape_dev *cdev,
> + const char *property, const char *value)
> +{
> + struct cape_bus *bus = cdev->bus;
> + struct device *dev = &cdev->dev;
> + struct device_node *pnode = cape_bus_to_parent_of_node(bus);
> + struct device_node *node;
> + const struct of_device_id *match;
> + const char* cp;
> + int cplen, l;
> +
> + dev_dbg(dev, "Iterating on parent of node "
> + "name='%s' type='%s' full_name='%s'\n",
> + pnode->name, pnode->type, pnode->full_name);
> +
> + match = NULL;
> + for_each_child_of_node(pnode, node) {
> +
> + dev->of_node = node;
> + match = of_match_device(dev->driver->of_match_table, dev);
> + if (!match)
> + goto next_node;
> +
> + cp = of_get_property(node, property, &cplen);
> + if (cp == NULL)
> + goto next_node;
> +
> + while (cplen > 0) {
> + if (of_compat_cmp(cp, value, strlen(value)) == 0)
> + break;
> + l = strlen(cp) + 1;
> + cp += l;
> + cplen -= l;
> + }
> +
> + /* matched */
> + if (cplen > 0)
> + break;
> +next_node:
> + match = NULL;
> + dev->of_node = NULL;
> + }
> +
> + if (match == NULL) {
> + dev_dbg(dev, "Failed to find matching child-node\n");
> + return NULL;
> + }
> +
> + dev_dbg(dev, "Found matching child node "
> + "name='%s' type='%s' "
> + "full_name='%s' (compatible='%s')\n",
> + node->name, node->type, node->full_name,
> + match->compatible);
> +
> + return match;
> +}
> +EXPORT_SYMBOL(capebus_of_match_device);
> +
> +struct device_node *
> +capebus_of_compatible_device_property_match(struct cape_dev *dev,
> + const struct of_device_id *matches,
> + const char *prop, const char *prop_value)
> +{
> + const struct of_device_id *match;
> + struct device_node *node, *cnode;
> + const char* cp;
> + int cplen, l;
> +
> + if (prop == NULL || prop_value == NULL)
> + goto try_non_property;
> +
> + /* at first try secondary match */
> + for_each_child_of_node(dev->dev.of_node, node) {
> +
> + cp = of_get_property(node, prop, &cplen);
> + if (cp == NULL)
> + continue;
> +
> + while (cplen > 0) {
> + if (of_compat_cmp(cp, prop_value,
> + strlen(prop_value)) == 0)
> + break;
> + l = strlen(cp) + 1;
> + cp += l;
> + cplen -= l;
> + }
> +
> + /* not matched */
> + if (cplen <= 0)
> + continue;
> +
> + /* now iterate in the children nodes */
> + for_each_child_of_node(node, cnode) {
> +
> + match = of_match_node(matches, cnode);
> + if (match) {
> + /* release reference to parent, keep this one */
> + of_node_put(node);
> + return cnode;
> + }
> + }
> + }
> +
> +try_non_property:
> + for_each_child_of_node(dev->dev.of_node, node) {
> +
> + match = of_match_node(matches, node);
> + if (match)
> + return node;
> + }
> +
> + return NULL;
> +}
> +EXPORT_SYMBOL(capebus_of_compatible_device_property_match);
> +
> +struct platform_device *
> +capebus_of_platform_compatible_device_create(struct cape_dev *dev,
> + const struct of_device_id *matches,
> + const char *pdev_name,
> + const char *prop, const char *prop_value)
> +{
> + struct device_node *node;
> + struct platform_device *pdev;
> +
> + node = capebus_of_compatible_device_property_match(dev, matches, prop,
> + prop_value);
> + if (node == NULL)
> + return ERR_PTR(-ENXIO);
> +
> + pdev = of_platform_device_create(node, pdev_name, dev->bus->dev.parent);
> +
> + /* release the reference to the node */
> + of_node_put(node);
> + node = NULL;
> +
> + if (pdev == NULL) {
> + dev_err(&dev->dev, "Failed to create platform device '%s'\n",
> + pdev_name);
> + return ERR_PTR(-ENODEV);
> + }
> +
> + return pdev;
> +}
> +EXPORT_SYMBOL(capebus_of_platform_compatible_device_create);
> +
> +struct device_node *
> +capebus_of_find_property_node(struct cape_dev *dev,
> + const char *prop, const char *prop_value,
> + const char *name)
> +{
> + struct device_node *node;
> + const char* cp;
> + int cplen, l;
> + struct property *pp;
> +
> + node = NULL;
> + if (prop == NULL || prop_value == NULL)
> + goto find_direct;
> +
> + /* at first try secondary match */
> + for_each_child_of_node(dev->dev.of_node, node) {
> +
> + cp = of_get_property(node, prop, &cplen);
> + if (cp == NULL)
> + continue;
> +
> + while (cplen > 0) {
> + if (of_compat_cmp(cp, prop_value,
> + strlen(prop_value)) == 0)
> + break;
> + l = strlen(cp) + 1;
> + cp += l;
> + cplen -= l;
> + }
> +
> + /* not matched */
> + if (cplen <= 0)
> + continue;
> +
> + /* found ? */
> + pp = of_find_property(node, name, NULL);
> + if (pp != NULL)
> + return node;
> + }
> +find_direct:
> + pp = of_find_property(dev->dev.of_node, name, NULL);
> + if (pp == NULL)
> + return NULL;
> +
> + return of_node_get(dev->dev.of_node);
> +}
> +EXPORT_SYMBOL_GPL(capebus_of_find_property_node);
> +
> +struct property *
> +capebus_of_find_property(struct cape_dev *dev,
> + const char *prop, const char *prop_value,
> + const char *name, int *lenp)
> +{
> + struct device_node *node;
> + struct property *pp;
> +
> + node = capebus_of_find_property_node(dev, prop, prop_value, name);
> + if (node == NULL)
> + return NULL;
> +
> + pp = of_find_property(node, name, lenp);
> +
> + of_node_put(node);
> +
> + return pp;
> +}
> +EXPORT_SYMBOL_GPL(capebus_of_find_property);
> +
> +const void *capebus_of_get_property(struct cape_dev *dev,
> + const char *prop, const char *prop_value,
> + const char *name, int *lenp)
> +{
> + struct property *pp;
> +
> + pp = capebus_of_find_property(dev, prop, prop_value, name, lenp);
> + return pp ? pp->value : NULL;
> +}
> +EXPORT_SYMBOL_GPL(capebus_of_get_property);
> +
> +/* node exists, but it's not available? make it so */
> +int capebus_of_device_node_enable(struct device_node *node)
> +{
> + struct property *prop;
> + int ret;
> +
> + prop = kzalloc(sizeof(*prop), GFP_KERNEL);
> + if (prop == NULL)
> + goto err_no_prop_mem;
> +
> + prop->name = kstrdup("status", GFP_KERNEL);
> + if (prop->name == NULL)
> + goto err_no_name_mem;
> +
> + prop->value = kstrdup("okay", GFP_KERNEL);
> + if (prop->value == NULL)
> + goto err_no_value_mem;
> +
> + prop->length = strlen(prop->value) + 1;
> + set_bit(OF_DYNAMIC, &prop->_flags);
> +
> + ret = prom_update_property(node, prop);
> + if (ret != 0)
> + goto err_update_failed;
> +
> + return 0;
> +
> +err_update_failed:
> + kfree(prop->value);
> +err_no_value_mem:
> + kfree(prop->name);
> +err_no_name_mem:
> + kfree(prop);
> +err_no_prop_mem:
> + return -ENOMEM;
> +}
> +EXPORT_SYMBOL_GPL(capebus_of_device_node_enable);
> +
> +/* Make sure this node is activated (even if it was disabled) */
> +int capebus_of_platform_device_enable(struct device_node *node)
> +{
> + struct platform_device *pdev, *ppdev;
> + int ret;
> +
> + if (of_device_is_available(node))
> + return 0;
> +
> + ret = capebus_of_device_node_enable(node);
> + if (ret != 0)
> + return ret;
> +
> + /* now we need to find the parent of the node */
> + ppdev = of_find_device_by_node(node->parent);
> +
> + pdev = of_platform_device_create(node, NULL,
> + ppdev ? &ppdev->dev : NULL);
> + if (IS_ERR_OR_NULL(pdev)) {
> + ret = pdev ? PTR_ERR(pdev) : -ENODEV;
> + return ret;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(capebus_of_platform_device_enable);
> diff --git a/drivers/capebus/capebus-probe.c b/drivers/capebus/capebus-probe.c
> new file mode 100644
> index 0000000..b46e915
> --- /dev/null
> +++ b/drivers/capebus/capebus-probe.c
> @@ -0,0 +1,320 @@
> +/*
> + * Capebus bus infrastructure
> + *
> + * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
> + * Copyright (C) 2012 Texas Instruments Inc.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_i2c.h>
> +#include <linux/of_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/err.h>
> +#include <linux/list.h>
> +#include <linux/mutex.h>
> +#include <linux/slab.h>
> +
> +#include <linux/capebus.h>
> +
> +LIST_HEAD(cape_buses);
> +EXPORT_SYMBOL(cape_buses);
> +
> +DEFINE_MUTEX(cape_buses_mutex);
> +EXPORT_SYMBOL(cape_buses_mutex);
> +
> +/*
> + * Cape Bus Class
> + */
> +static void release_capebus_dev(struct device *dev)
> +{
> + struct cape_dev *cape_dev = to_cape_dev(dev);
> +
> + kfree(cape_dev);
> +}
> +
> +static struct class capebus_class = {
> + .name = "capebus",
> + .dev_release = &release_capebus_dev,
> +};
> +
> +static int __init capebus_class_init(void)
> +{
> + return class_register(&capebus_class);
> +}
> +postcore_initcall(capebus_class_init);
> +
> +static struct cape_bus *cape_bus_find(const char *name, int busno)
> +{
> + struct cape_bus *bus;
> + int found;
> +
> + if (busno < 0)
> + return NULL;
> +
> + found = 0;
> + cape_bus_for_each(bus) {
> + if (strcmp(name, bus->name) == 0 && bus->busno == busno) {
> + found = 1;
> + break;
> + }
> + }
> + return found ? bus : NULL;
> +}
> +
> +static int cape_bus_pick_busno(const char *name, int busno)
> +{
> + struct cape_bus *bus;
> +
> + BUG_ON(name == NULL);
> +
> + /* fixed id */
> + if (busno >= 0)
> + return busno;
> +
> + /* dynamic id */
> + busno = -1;
> + cape_bus_for_each(bus) {
> + /* name must match */
> + if (strcmp(name, bus->name) != 0)
> + continue;
> + busno = max(busno, bus->busno);
> + }
> + return busno + 1;
> +}
> +
> +int cape_bus_register(struct cape_bus *bus, const char *name, int busno,
> + struct device *parent, struct cape_bus_ops *ops)
> +{
> + struct cape_bus *b2;
> + int r;
> +
> + if (name == NULL)
> + return -EINVAL;
> +
> + INIT_LIST_HEAD(&bus->node);
> + INIT_LIST_HEAD(&bus->devices);
> + INIT_LIST_HEAD(&bus->slots);
> +
> + /* do everything under lock */
> + mutex_lock(&cape_buses_mutex);
> +
> + b2 = cape_bus_find(name, busno);
> + if (b2 != NULL) {
> + if (parent != NULL)
> + dev_err(parent, "capebus %s:%d in use\n", name, busno);
> + else
> + pr_err("capebus %s:%d in use\n", name, busno);
> + r = -EBUSY;
> + goto err_unlock;
> + }
> + bus->name = name;
> + bus->busno = cape_bus_pick_busno(name, busno);
> + bus->ops = ops;
> +
> + bus->dev.class = &capebus_class;
> + bus->dev.parent = parent;
> + dev_set_name(&bus->dev, "%s:%d", bus->name, bus->busno);
> + r = device_register(&bus->dev);
> + if (r != 0) {
> + if (parent != NULL)
> + dev_err(parent, "capebus #%d failed to register dev\n",
> + bus->busno);
> + else
> + pr_err("capebus #%d failed to register dev\n",
> + bus->busno);
> + goto err_unlock;
> + }
> +
> + list_add_tail(&bus->node, &cape_buses);
> + mutex_unlock(&cape_buses_mutex);
> +
> + dev_info(&bus->dev, "Registered\n");
> +
> + return 0;
> +err_unlock:
> + mutex_unlock(&cape_buses_mutex);
> + return r;
> +}
> +
> +int cape_bus_deregister(struct cape_bus *bus)
> +{
> + return -EINVAL; /* not yet supported */
> +}
> +
> +/* must have cape_buses_mutex */
> +struct cape_slot *cape_slot_find(struct cape_bus *bus, int slotno)
> +{
> + struct cape_slot *slot;
> + int found;
> +
> + found = 0;
> + cape_slot_for_each(bus, slot) {
> + if (slot->slotno == slotno) {
> + found = 1;
> + break;
> + }
> + }
> + return found ? slot : NULL;
> +}
> +
> +/**
> + * cape_bus_release_dev - free a cape device structure when all users
> + * of it are finished.
> + * @dev: device that's been disconnected
> + *
> + * Will be called only by the device core when all users of this cape device are
> + * done.
> + */
> +static void cape_bus_release_dev(struct device *dev)
> +{
> + struct cape_dev *cdev;
> +
> + cdev = to_cape_dev(dev);
> + /* cape_release_capabilities(cdev); TODO */
> + /* cape_release_of_node(cdev); TODO */
> + kfree(cdev);
> +}
> +
> +/* mutex lock must be held */
> +static struct cape_dev *cape_bus_scan_slot(struct cape_slot *slot)
> +{
> + struct cape_bus *bus = slot->bus;
> + struct cape_dev *dev;
> + const struct cape_device_id *id;
> +
> + /* get the ID (if a device exists) */
> + id = bus->ops->get_dev_id(slot);
> + if (id == NULL)
> + return ERR_PTR(-ENODEV);
> +
> + /* slot must not have a device yet */
> + dev = slot->dev;
> + if (dev == NULL) {
> + dev = kzalloc(sizeof(*dev), GFP_KERNEL);
> + if (dev == NULL) {
> + dev_info(&bus->dev, "Failed to allocate cape device "
> + "for slot #%d\n", slot->slotno);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + INIT_LIST_HEAD(&dev->bus_list);
> + dev->bus = bus;
> + dev->slot = slot;
> + }
> +
> + dev->id = id;
> + dev->text_id = bus->ops->get_text_dev_id(slot);
> +
> + /* capebus_set_of_node(dev); TODO */
> +
> + return dev;
> +}
> +
> +int cape_bus_scan_one_slot(struct cape_bus *bus, struct cape_slot *slot)
> +{
> + struct cape_dev *dev;
> + int r;
> +
> + mutex_lock(&cape_buses_mutex);
> +
> + dev = slot->dev;
> + if (dev == NULL) {
> +
> + dev = cape_bus_scan_slot(slot);
> + if (IS_ERR(dev)) {
> + r = PTR_ERR(dev);
> + goto err_out;
> + }
> +
> + dev_info(&bus->dev, "Slot #%d id='%s'\n", slot->slotno,
> + dev->text_id ? dev->text_id : "");
> +
> + slot->dev = dev;
> +
> + dev->dev.release = cape_bus_release_dev;
> + dev->dev.parent = &dev->bus->dev;
> + dev->dev.bus = &capebus_bus_type;
> + dev_set_name(&dev->dev, "%s-%d:%d",
> + dev->bus->name, dev->bus->busno,
> + dev->slot->slotno);
> +
> + list_add_tail(&dev->bus_list, &bus->devices);
> +
> + } else {
> + dev_info(&bus->dev, "Slot #%d id='%s' - rescan\n", slot->slotno,
> + dev->text_id ? dev->text_id : "");
> +
> + if (dev->added) {
> + r = -EEXIST;
> + goto err_out;
> + }
> + }
> +
> + r = device_register(&dev->dev);
> + if (r != 0) {
> + dev_info(&bus->dev, "Slot #%d id='%s' - "
> + "Failed to register\n",
> + slot->slotno,
> + dev->text_id ? dev->text_id : "");
> + r = 0;
> + } else {
> + if (dev->bus->ops->dev_registered)
> + dev->bus->ops->dev_registered(dev);
> + }
> +
> +err_out:
> + mutex_unlock(&cape_buses_mutex);
> +
> + return r;
> +}
> +
> +int cape_bus_register_slot(struct cape_bus *bus, struct cape_slot *slot,
> + int slotno)
> +{
> + struct cape_slot *s2;
> + int r;
> +
> + r = 0;
> +
> + /* invalid (slot must always be numbered - no hotplug) */
> + if (slotno < 0) {
> + dev_err(&bus->dev, "Slot registration #%d failed\n", slotno);
> + return -EINVAL;
> + }
> +
> + mutex_lock(&cape_buses_mutex);
> + s2 = cape_slot_find(bus, slotno);
> + if (s2 != NULL) {
> + dev_err(&bus->dev, "Slot #%d already exists\n", slotno);
> + mutex_unlock(&cape_buses_mutex);
> + return -EINVAL;
> + }
> +
> + INIT_LIST_HEAD(&slot->node);
> + slot->bus = bus;
> + list_add(&slot->node, &bus->slots);
> + slot->slotno = slotno;
> + slot->dev = NULL;
> + mutex_unlock(&cape_buses_mutex);
> +
> + dev_info(&bus->dev, "Slot #%d registered\n", slot->slotno);
> +
> + return cape_bus_scan_one_slot(bus, slot);
> +}
> diff --git a/drivers/capebus/capebus-sysfs.c b/drivers/capebus/capebus-sysfs.c
> new file mode 100644
> index 0000000..81c21fe
> --- /dev/null
> +++ b/drivers/capebus/capebus-sysfs.c
> @@ -0,0 +1,52 @@
> +/*
> + * drivers/capebus/capebus-sysfs.c
> + *
> + * sysfs for capebus devices
> + *
> + * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
> + * Copyright (C) 2012 Texas Instruments Inc.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + * Modeled after PCI's pci-sysfs.c
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/stat.h>
> +#include <linux/export.h>
> +#include <linux/fs.h>
> +#include <linux/slab.h>
> +#include <linux/pm_runtime.h>
> +
> +#include <linux/capebus.h>
> +
> +static ssize_t id_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct cape_dev *cdev;
> +
> + cdev = to_cape_dev(dev);
> + return sprintf(buf, "%s\n", cdev->text_id);
> +}
> +
> +struct device_attribute capebus_dev_attrs[] = {
> + __ATTR_RO(id),
> + __ATTR_NULL,
> +};
> +
> +struct bus_attribute capebus_bus_attrs[] = {
> + __ATTR_NULL
> +};
> diff --git a/include/linux/capebus.h b/include/linux/capebus.h
> new file mode 100644
> index 0000000..7524401
> --- /dev/null
> +++ b/include/linux/capebus.h
> @@ -0,0 +1,298 @@
> +/*
> + * capebus.h
> + *
> + * Cape bus defines and function prototypes
> + *
> + * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
> + * Copyright (C) 2012 Texas Instruments Inc.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +#ifndef LINUX_CAPEBUS_H
> +#define LINUX_CAPEBUS_H
> +
> +#include <linux/list.h>
> +#include <linux/device.h>
> +#include <linux/spinlock.h>
> +#include <linux/types.h>
> +#include <linux/atomic.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +
> +struct cape_device_id {
> + const char *cntrlboard; /* controlling board; i.e. "beaglebone" */
> + int len; /* opaque addressing data */
> + const void *data;
> +};
> +
> +struct cape_dev;
> +struct cape_bus;
> +struct cape_slot;
> +
> +struct cape_slot {
> + struct list_head node;
> + struct cape_bus *bus; /* the bus this slot is on */
> + int slotno; /* index of this slot */
> + struct cape_dev *dev; /* the device (if found) */
> +};
> +
> +struct cape_driver {
> + struct list_head node;
> + int (*probe)(struct cape_dev *dev, const struct cape_device_id *id);
> + void (*remove)(struct cape_dev *dev);
> + int (*suspend) (struct cape_dev *dev, pm_message_t state);
> + int (*suspend_late) (struct cape_dev *dev, pm_message_t state);
> + int (*resume_early) (struct cape_dev *dev);
> + int (*resume) (struct cape_dev *dev);
> + void (*shutdown) (struct cape_dev *dev);
> + struct device_driver driver;
> +};
> +
> +/*
> + * capebus_register_driver must be a macro so that
> + * KBUILD_MODNAME can be expanded
> + */
> +#define capebus_register_driver(driver) \
> + __capebus_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
> +
> +int __capebus_register_driver(struct cape_driver *drv, struct module *owner,
> + const char *mod_name);
> +
> +void capebus_unregister_driver(struct cape_driver *dev);
> +
> +/**
> + * module_capebus_driver() - Helper macro for registering a capebus driver
> + * @__capebus_driver: capebus_driver struct
> + *
> + * Helper macro for capebus drivers which do not do anything special in module
> + * init/exit. This eliminates a lot of boilerplate. Each module may only
> + * use this macro once, and calling it replaces module_init() and module_exit()
> + */
> +#define module_capebus_driver(__capebus_driver) \
> + module_driver(__capebus_driver, capebus_register_driver, \
> + capebus_unregister_driver)
> +
> +#define to_cape_driver(n) container_of(n, struct cape_driver, driver)
> +
> +struct cape_bus_ops {
> + const struct cape_device_id *(*get_dev_id)(struct cape_slot *slot);
> + const char *(*get_text_dev_id)(struct cape_slot *slot);
> + int (*dev_probed)(struct cape_dev *dev); /* probed succesfully */
> + void (*dev_removed)(struct cape_dev *dev); /* removed */
> + int (*dev_registered)(struct cape_dev *dev); /* registered OK */
> +};
> +
> +struct cape_bus {
> + struct list_head node;
> + const char *name;
> + struct list_head devices;
> + struct cape_dev *self;
> + struct list_head slots;
> + struct cape_bus_ops *ops;
> + int busno;
> + struct device dev;
> + /* TODO: resources.... */
> +};
> +
> +#define to_cape_bus(n) container_of(n, struct cape_bus, dev)
> +
> +#define cape_bus_to_parent_of_node(n) ((n)->dev.parent->of_node)
> +
> +struct cape_dev {
> + struct list_head bus_list; /* node in per-bus list */
> + struct cape_bus *bus; /* bus this device is on */
> + struct cape_slot *slot; /* cape slot of this device */
> + struct cape_driver *driver; /* driver of this device */
> + struct device dev;
> + atomic_t enable_cnt; /* capebus_enable_device */
> + /* has been called */
> + const struct cape_device_id *id;
> + const char *text_id;
> + unsigned int added : 1; /* device has been added */
> + void *drv_priv; /* driver private data */
> +};
> +
> +#define to_cape_dev(n) container_of(n, struct cape_dev, dev)
> +
> +struct cape_dev *capebus_dev_get(struct cape_dev *dev);
> +void capebus_dev_put(struct cape_dev *dev);
> +
> +/* must have cape_buses_mutex */
> +#define cape_bus_for_each(_bus) \
> + list_for_each_entry(_bus, &cape_buses, node)
> +
> +#define cape_bus_for_each_safe(_bus, _busn) \
> + list_for_each_entry_safe(_bus, _busn, &cape_buses, node)
> +
> +int cape_bus_register(struct cape_bus *bus, const char *name, int busno,
> + struct device *parent, struct cape_bus_ops *ops);
> +
> +/* must have cape_buses_mutex */
> +#define cape_slot_for_each(_bus, _slot) \
> + list_for_each_entry(_slot, &(_bus)->slots, node)
> +
> +#define cape_slot_for_each_safe(_bus, _slot, _slotn) \
> + list_for_each_entry_safe(_slot, _slotn, &(_bus)->slots, node)
> +
> +int cape_bus_register_slot(struct cape_bus *bus,
> + struct cape_slot *slot, int slotno);
> +
> +int cape_bus_scan_one_slot(struct cape_bus *bus, struct cape_slot *slot);
> +int cape_bus_scan(struct cape_bus *bus);
> +
> +extern struct list_head cape_buses;
> +extern struct mutex cape_buses_mutex;
> +
> +static inline int capebus_is_enabled(struct cape_dev *cdev)
> +{
> + return atomic_read(&cdev->enable_cnt) > 0;
> +}
> +
> +static inline int capebus_enable_device(struct cape_dev *cdev)
> +{
> + if (atomic_add_return(1, &cdev->enable_cnt) > 1)
> + return 0; /* already enabled */
> +
> + /* XXX do enable */
> +
> + return 0;
> +}
> +
> +static inline void capebus_disable_device(struct cape_dev *cdev)
> +{
> + if (atomic_sub_return(1, &cdev->enable_cnt) != 0)
> + return;
> +
> + /* callback to disable device? */
> +}
> +
> +static inline int capebus_enable_wake(struct cape_dev *dev, int what)
> +{
> + return 0;
> +}
> +
> +extern struct device_attribute capebus_dev_attrs[];
> +extern struct bus_attribute capebus_bus_attrs[];
> +
> +extern struct bus_type capebus_bus_type;
> +
> +const struct of_device_id *
> +capebus_of_match_device(struct cape_dev *cdev,
> + const char *property, const char *value);
> +
> +struct device_node *
> +capebus_of_compatible_device_property_match(struct cape_dev *dev,
> + const struct of_device_id *matches,
> + const char *prop, const char *prop_value);
> +
> +struct platform_device *
> +capebus_of_platform_compatible_device_create(struct cape_dev *dev,
> + const struct of_device_id *matches,
> + const char *pdev_name,
> + const char *prop, const char *prop_value);
> +
> +/* of tree support */
> +
> +struct device_node *
> +capebus_of_find_property_node(struct cape_dev *dev,
> + const char *prop, const char *prop_value,
> + const char *name);
> +
> +struct property *
> +capebus_of_find_property(struct cape_dev *dev,
> + const char *prop, const char *prop_value,
> + const char *name, int *lenp);
> +
> +const void *capebus_of_get_property(struct cape_dev *dev,
> + const char *prop, const char *prop_value,
> + const char *name, int *lenp);
> +
> +static inline int capebus_of_property_read_u32_array(struct cape_dev *dev,
> + const char *prop, const char *prop_value,
> + const char *name, u32 *out_values, size_t sz)
> +{
> + struct device_node *node;
> + int ret;
> +
> + node = capebus_of_find_property_node(dev, prop, prop_value, name);
> + ret = of_property_read_u32_array(node, name, out_values, sz);
> + of_node_put(node);
> + return ret;
> +}
> +
> +static inline int capebus_of_property_read_u32(struct cape_dev *dev,
> + const char *prop, const char *prop_value,
> + const char *name, u32 *out_value)
> +{
> + return capebus_of_property_read_u32_array(dev, prop,
> + prop_value, name, out_value, 1);
> +}
> +
> +static inline bool capebus_of_property_read_bool(struct cape_dev *dev,
> + const char *prop, const char *prop_value,
> + const char *name)
> +{
> + struct device_node *node;
> + bool ret;
> +
> + node = capebus_of_find_property_node(dev, prop, prop_value, name);
> + ret = of_property_read_bool(node, name);
> + of_node_put(node);
> + return ret;
> +}
> +
> +static inline int capebus_of_property_read_string(struct cape_dev *dev,
> + const char *prop, const char *prop_value,
> + const char *name, const char **out_string)
> +{
> + struct device_node *node;
> + int ret;
> +
> + node = capebus_of_find_property_node(dev, prop, prop_value, name);
> + ret = of_property_read_string(node, name, out_string);
> + of_node_put(node);
> + return ret;
> +}
> +
> +static inline int capebus_of_property_read_string_index(struct cape_dev *dev,
> + const char *prop, const char *prop_value,
> + const char *name, int index, const char **out_string)
> +{
> + struct device_node *node;
> + int ret;
> +
> + node = capebus_of_find_property_node(dev, prop, prop_value, name);
> + ret = of_property_read_string_index(node, name, index, out_string);
> + of_node_put(node);
> + return ret;
> +}
> +
> +static inline int capebus_of_property_read_u64(struct cape_dev *dev,
> + const char *prop, const char *prop_value,
> + const char *name, u64 *out_value)
> +{
> + struct device_node *node;
> + int ret;
> +
> + node = capebus_of_find_property_node(dev, prop, prop_value, name);
> + ret = of_property_read_u64(node, name, out_value);
> + of_node_put(node);
> + return ret;
> +}
> +
> +int capebus_of_device_node_enable(struct device_node *node);
> +int capebus_of_platform_device_enable(struct device_node *node);
> +
> +#endif
> --
> 1.7.12
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ 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