* [PATCH 2/4] msm: scm: Fix improper register assignment
From: Stephen Boyd @ 2011-02-24 18:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298573085-23217-1-git-send-email-sboyd@codeaurora.org>
Assign the registers used in the inline assembly immediately
before the inline assembly block. This ensures the compiler
doesn't optimize away dead register assignments when it
shouldn't.
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/scm.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
index ba57b5a..5eddf54 100644
--- a/arch/arm/mach-msm/scm.c
+++ b/arch/arm/mach-msm/scm.c
@@ -264,13 +264,16 @@ u32 scm_get_version(void)
{
int context_id;
static u32 version = -1;
- register u32 r0 asm("r0") = 0x1 << 8;
- register u32 r1 asm("r1") = (u32)&context_id;
+ register u32 r0 asm("r0");
+ register u32 r1 asm("r1");
if (version != -1)
return version;
mutex_lock(&scm_lock);
+
+ r0 = 0x1 << 8;
+ r1 = (u32)&context_id;
asm volatile(
__asmeq("%0", "r1")
__asmeq("%1", "r0")
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH 1/4] msm: scm: Mark inline asm as volatile
From: Stephen Boyd @ 2011-02-24 18:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298573085-23217-1-git-send-email-sboyd@codeaurora.org>
We don't want the compiler to remove these asm statements or
reorder them in any way. Mark them as volatile to be sure.
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/scm.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
index f4b9bc9..ba57b5a 100644
--- a/arch/arm/mach-msm/scm.c
+++ b/arch/arm/mach-msm/scm.c
@@ -174,7 +174,7 @@ static u32 smc(u32 cmd_addr)
register u32 r0 asm("r0") = 1;
register u32 r1 asm("r1") = (u32)&context_id;
register u32 r2 asm("r2") = cmd_addr;
- asm(
+ asm volatile(
__asmeq("%0", "r0")
__asmeq("%1", "r0")
__asmeq("%2", "r1")
@@ -271,7 +271,7 @@ u32 scm_get_version(void)
return version;
mutex_lock(&scm_lock);
- asm(
+ asm volatile(
__asmeq("%0", "r1")
__asmeq("%1", "r0")
__asmeq("%2", "r1")
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH 0/4] SCM fixes and updates
From: Stephen Boyd @ 2011-02-24 18:44 UTC (permalink / raw)
To: linux-arm-kernel
These are a few updates to SCM. The first two patches fix some
bad code generation. The next patch saves a couple instructions
on the slow path and the final patch determines the cacheline
size dynamically instead of statically.
Stephen Boyd (4):
msm: scm: Mark inline asm as volatile
msm: scm: Fix improper register assignment
msm: scm: Check for interruption immediately
msm: scm: Get cacheline size from CTR
arch/arm/mach-msm/scm.c | 75 +++++++++++++++++++++++++++-------------------
1 files changed, 44 insertions(+), 31 deletions(-)
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply
* [PATCH] OMAP4: clock: Support divider selection for auxclks
From: Paul Walmsley @ 2011-02-24 18:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298557696-1726-1-git-send-email-rnayak@ti.com>
Hi Rajendra,
On Thu, 24 Feb 2011, Rajendra Nayak wrote:
> On OMAP4 the auxclk nodes (part of SCRM) support both
> divider as well as parent selection.
> Supporting this requires splitting the existing nodes
> (which support only parent selection) into
> two nodes, one for parent and another for
> divider selection.
> The nodes for parent selection are named
> auxclk*_src_ck and the ones for divider
> selection as auxclk*_ck
>
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> Tested-by: Anand Gadiyar <gadiyar@ti.com>
Thanks. Has the autogeneration script been updated?
- Paul
^ permalink raw reply
* [PATCH v3 2/2] OMAP: IOMMU: add support to callback during fault handling
From: Guzman Lugo, Fernando @ 2011-02-24 17:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110224112912.GQ3528@legolas.emea.dhcp.ti.com>
On Thu, Feb 24, 2011 at 5:29 AM, Felipe Balbi <balbi@ti.com> wrote:
> On Thu, Feb 24, 2011 at 01:26:05PM +0200, David Cohen wrote:
>> On Thu, Feb 24, 2011 at 10:35 AM, Felipe Balbi <balbi@ti.com> wrote:
>> > Hi,
>> >
>> > On Wed, Feb 23, 2011 at 10:09:05PM +0200, Sakari Ailus wrote:
>> >> > In OMAP4 the cortex M3 is a double core processor and as each core is
>> >> > running they own version of the RTOS we threat them independently. So
>> >> > our driver which controls the remote processor sees two processor but
>> >> > both use the same iommu hw. When a iommu fault happens, at this
>> >> > moment, it is consider as a faltal error and it is no managed to
>> >> > recover and continue, instead a restart of the processor is needed, if
>> >> > the fault happens in core0 we need to reset core1 too and vice versa.
>> >> > if the iommu would support several user callbacks, we can register the
>> >> > callback which resets core0 and also the callback which resets core1
>> >> > and treat them as totally independent processors. Also we have an
>> >> > error event notifier driver, which is only in charge of notifying
>> >> > error events to userspace, so we would have multiple callbacks we
>> >> > could do this
>> >>
>> >> The original purpose of the patch, as far as I understand, is to allow
>> >> getting useful information for debugging purposes should an iommu fault
>> >> happen.
>> >>
>> >> Also, I'm not sure it's necessarily a good idea to just go and reset
>> >> the M3 cores in case an iommu fault happens --- this is very probably a
>> >> grave bug in the software running on those M3s. It should be fixed
>> >> instead of just hiding it. There will be consequences to host side as
>> >
>> > I have to agree here. Besides the fact that multiple callbacks is
>> > outside the scope of this patch.
>>
>> This patch is already acked. What about leave it as it is and discuss
>> multiple callbacks before release a new patch to support it?
>
> fine by me ;-)
Ok, maybe it was too late to change it, due to it is already acked, I
just wanted to avoid change isr here and then change it on other
patch. it is ok then.
Regards,
Fernando.
>
> --
> balbi
>
^ permalink raw reply
* [PATCH] omap4: Fix ULPI PHY init for ES1.0 SDP (Re: 4430SDP boot failure)
From: Tony Lindgren @ 2011-02-24 17:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <84fafb82318b1287513d198c6535eb59@mail.gmail.com>
* Santosh Shilimkar <santosh.shilimkar@ti.com> [110212 00:45]:
> Tony,
> > -----Original Message-----
> > From: Santosh Shilimkar [mailto:santosh.shilimkar at ti.com]
> > Sent: Thursday, February 03, 2011 2:13 PM
> > To: Tony Lindgren
> > Cc: Anand Gadiyar; Russell King - ARM Linux; linux-arm-
> > kernel at lists.infradead.org; linux-omap at vger.kernel.org; Keshava
> > Munegowda; Felipe Balbi
> > Subject: RE: [PATCH] omap4: Fix ULPI PHY init for ES1.0 SDP (Re:
> > 4430SDP boot failure)
> >
> > > -----Original Message-----
> > > From: Tony Lindgren [mailto:tony at atomide.com]
> > > Sent: Thursday, February 03, 2011 1:19 AM
> > > To: Santosh Shilimkar
> > > Cc: Anand Gadiyar; Russell King - ARM Linux; linux-arm-
> > > kernel at lists.infradead.org; linux-omap at vger.kernel.org; Keshava
> > > Munegowda; Felipe Balbi
> > > Subject: Re: [PATCH] omap4: Fix ULPI PHY init for ES1.0 SDP (Re:
> > > 4430SDP boot failure)
> > >
> > > * Santosh Shilimkar <santosh.shilimkar@ti.com> [110201 22:04]:
> > > > >
> > > > > It's a ES1.0 blaze, with the patch below it reboots early
> > > > > during the boot. I also have to disable omap_l2_cache_init
> > > > > on this board to get it to boot.
> > > > >
> > > > Do you still get this problem with 'omap_l2_cache_init' ?
> > > > As reported earlier, we don't see this issue on ES1.0
> > > > SDP.
> > >
> > > Yeah I do, it rarely makes it to the userspace. Works reliably
> > > if I disable omap_l2_cache_init.
> > >
> > Ok. I shall try few experiments and try to reproduce it
>
> Not sure if it's the same issue but I managed to reproduce the
> issue on ES2.0 itself. And after some experiments, it boiled
> down to the V6 and V7 issue. By disabling OMAP2 from the build,
> everything was fine again.
Was this with linux-omap master branch or mainline?
The V6 vs V7 issues should be sorted out with Russell's patches that
we also have now in linux-omap master branch.
Regards,
Tony
^ permalink raw reply
* [PATCH V11 2/4] ptp: Added a clock that uses the eTSEC found on the MPC85xx.
From: Scott Wood @ 2011-02-24 17:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110224165004.GB15234@riccoc20.at.omicron.at>
On Thu, 24 Feb 2011 17:50:04 +0100
Richard Cochran <richardcochran@gmail.com> wrote:
> On Wed, Feb 23, 2011 at 01:24:44PM -0600, Scott Wood wrote:
> > Whatever string is used should be written into a binding document.
> >
> > fsl,etsec-v1.6-ptp seems like it would be just as good for that purpose.
> >
> > Even just fsl,etsec-ptp will identify the binding, though it's lacking in
> > identifying the hardware (in the absence of access to the eTSEC ID
> > registers).
>
> I read the conversation, and I don't mind admitting that I do not
> understand what you both are arguing/discussing about.
>
> How should I set the strings? Like this?
>
> arch/powerpc/boot/dts/mpc8313erdb.dts:
> ptp_clock at 24E00 {
> compatible = "fsl,mpc8313-etsec-ptp";
> }
> arch/powerpc/boot/dts/mpc8572ds.dts:
> ptp_clock at 24E00 {
> compatible = "fsl,mpc8572-etsec-ptp";
> }
> arch/powerpc/boot/dts/p2020ds.dts:
> ptp_clock at 24E00 {
> compatible = "fsl,p2020ds-etsec-ptp";
> }
> arch/powerpc/boot/dts/p2020rdb.dts:
> ptp_clock at 24E00 {
> compatible = "fsl,p2020rdb-etsec-ptp";
> }
>
> drivers/net/gianfar_ptp.c:
>
> static struct of_device_id match_table[] = {
> { .compatible = "fsl,mpc8313-etsec-ptp" },
> { .compatible = "fsl,mpc8572-etsec-ptp" },
> { .compatible = "fsl,p2020ds-etsec-ptp" },
> { .compatible = "fsl,p2020rdb-etsec-ptp" },
> {},
> };
Those last two are boards, not chips. I don't think even Grant is asking
to take things that far.
My vote, if it goes in a separate node at all, is "fsl,etsec-ptp", and let
the driver use SVR. Even encoding an etsec version in the compatible
string would be difficult, unless fixed up by u-boot, as it appears to
differ based on chip revision (and the chip manuals seem to often not match
the hardware regarding the advertised eTSEC revision) and we don't normally
have separate dts files for different revisions of the same chip. Plus,
our docs (at least the public ones) don't seem to be very helpful in
determining what version of eTSEC implies what.
If you want to use chip-based compatibles instead, then use the actual name
of the chip. You'll need to verify 100% compatibility if you want to claim
compatibility with another chip; it's probably easier/safer to just list
every single Freescale chip that has this type of PTP in a huge compatible
table, like PCI drivers do.
-Scott
^ permalink raw reply
* [PATCH V11 2/4] ptp: Added a clock that uses the eTSEC found on the MPC85xx.
From: Richard Cochran @ 2011-02-24 17:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110223165058.GE14597@angua.secretlab.ca>
On Wed, Feb 23, 2011 at 09:50:58AM -0700, Grant Likely wrote:
> On Wed, Feb 23, 2011 at 11:38:17AM +0100, Richard Cochran wrote:
> > +Clock Properties:
> > +
> > + - tclk-period Timer reference clock period in nanoseconds.
> > + - tmr-prsc Prescaler, divides the output clock.
> > + - tmr-add Frequency compensation value.
> > + - cksel 0= external clock, 1= eTSEC system clock, 3= RTC clock input.
> > + Currently the driver only supports choice "1".
>
> I'd be hesitant about defining something that isn't actually
> implemented yet. You may find the binding to be insufficient at a
> later date.
Okay, I'll remove it.
We never got the external VCO working anyhow.
> > + - tmr-fiper1 Fixed interval period pulse generator.
> > + - tmr-fiper2 Fixed interval period pulse generator.
> > + - max-adj Maximum frequency adjustment in parts per billion.
>
> These are all custom properties (not part of any shared binding) so
> they should probably be prefixed with 'fsl,'.
Okay, fine.
> > + The calculation for tmr_fiper2 is the same as for tmr_fiper1. The
> > + driver expects that tmr_fiper1 will be correctly set to produce a 1
> > + Pulse Per Second (PPS) signal, since this will be offered to the PPS
> > + subsystem to synchronize the Linux clock.
>
> Good documentation, thanks. Question though, how many of these values
> will the end user (or board builder) be likely to want to change. It
> is risky encoding the calculation results into the device tree when
> they aren't the actually parameters that will be manipulated, or at
> least very user-unfriendly.
The whole thing is pretty opaque, and my explanation is (IMHO) way
better that Freescale's documentation of how the fipers work.
The board designer / system designer will want to set these carefully,
but never change them. Basically, for a given input clock, there is
only one optimal setting.
I think the device tree is the right place for that kind of setting.
The fiper1 signal should always be a 1 PPS. We could make fiper2 run
time programmable via PHC ioctls, but I think this can wait.
> > + etsects->irq = irq_of_parse_and_map(node, 0);
>
> Use platform_get_irq().
Okay.
> > + etsects->regs = of_iomap(node, 0);
>
> Use platform_get_resource(), and don't forget to request the
> resources.
Okay, but didn't you tell me before to do this way?
http://marc.info/?l=linux-netdev&m=127662247203659&w=4
> > +static struct of_platform_driver gianfar_ptp_driver = {
>
> Use a platform_driver instead. of_platform_driver is deprecated and
> being removed.
Ja, should have noticed that myself, sorry.
> > +++ b/drivers/net/gianfar_ptp_reg.h
>
> This data is only used by gianfar_ptp.c, so there is no need for a
> separate include file. Move the contents of gianfar_ptp_reg.h into
> gianfar_ptp.c
You are right, of course, since private #defines and declarations
should simply stay in their .c files. Some people think that all
#defines and declarations must go into a header file.
I am not one of those people, but in this case, I generated the file
from a little tool I wrote and so kept it separate.
Still, it is no trouble to combine the header into the driver .c file.
Thanks for your review,
Richard
^ permalink raw reply
* [PATCH V11 2/4] ptp: Added a clock that uses the eTSEC found on the MPC85xx.
From: Scott Wood @ 2011-02-24 17:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110224163944.GA15234@riccoc20.at.omicron.at>
On Thu, 24 Feb 2011 17:39:44 +0100
Richard Cochran <richardcochran@gmail.com> wrote:
> On Wed, Feb 23, 2011 at 10:54:59AM -0700, Grant Likely wrote:
> > On Wed, Feb 23, 2011 at 11:26:12AM -0600, Scott Wood wrote:
>
> > > The eTSEC revision is probeable as well, but due the way PTP is described as
> > > a separate node, the driver doesn't have straightforward access to those
> > > registers.
> >
> > Ignorant question: Should the ptp be described as a separate node?
>
> Well, the PTP Hardware Clock function is logically separate from the
> MAC function.
The eTSEC node doesn't describe the MAC function, it describes the whole
device (or at least it should... we make an exception for MDIO, which
should probably have been a subnode instead).
> PHCs can be implemented in the MAC, in the PHY, or in
> between in an FPGA on MII bus.
>
> If the PHC is in the MAC, then it might be wise to implement one
> driver that offers both the MAC and the PHC.
>
> In the case of gianfar, it is not really necessary to combine the PHC
> into the gianfar driver, since the registers are pretty well
> separated.
How the drivers are structured in Linux is a separate concern from how the
devices are described in the device tree. The tree is supposed to be an
OS-independent representation of hardware.
If Linux has multiple drivers that correspond to portions of one node, a
toplevel driver can register platform devices for the components, adding
in any additional information like versioning that it gets from the
toplevel registers.
-Scott
^ permalink raw reply
* mxs: name##_set_rate broken
From: Uwe Kleine-König @ 2011-02-24 16:57 UTC (permalink / raw)
To: linux-arm-kernel
Hello Shawn,
for the lcdif clock get_rate looks as follows:
read div from HW_CLKCTRL_DIS_LCDIF.DIV
return clk_get_rate(clk->parent) / div
with clk->parent being ref_pix_clk on our system.
ref_pix_clk's rate depends on HW_CLKCTRL_FRAC1.PIXFRAC.
The set_rate function for lcdif does:
parent_rate = clk_get_rate(clk->parent);
based on that calculate frac and div such that
parent_rate * 18 / frac / div is near the requested rate.
HW_CLKCTRL_FRAC1.PIXFRAC is updated with frac
HW_CLKCTRL_DIS_LCDIF.DIV is updated with div
For this calculation to be correct the parent_rate needs to be
initialized not with the clock rate of lcdif's parent (i.e. ref_pix) but
that of its grandparent (i.e. ref_pix' parent == pll0_clk)
I think the else branch to if (clk->parent == &ref_xtal_clk) of
name##_set_rate is broken for all clocks, but Sascha and I didn't
verified that. Our local fix is:
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
index febd787..7a26edd 100644
--- a/arch/arm/mach-mxs/clock-mx28.c
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -295,11 +295,11 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
unsigned long diff, parent_rate, calc_rate; \
int i; \
\
- parent_rate = clk_get_rate(clk->parent); \
div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV; \
bm_busy = BM_CLKCTRL_##dr##_BUSY; \
\
if (clk->parent == &ref_xtal_clk) { \
+ parent_rate = clk_get_rate(clk->parent); \
div = DIV_ROUND_UP(parent_rate, rate); \
if (clk == &cpu_clk) { \
div_max = BM_CLKCTRL_CPU_DIV_XTAL >> \
@@ -309,6 +309,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
if (div == 0 || div > div_max) \
return -EINVAL; \
} else { \
+ parent_rate = clk_get_rate(&pll0_clk); \
rate >>= PARENT_RATE_SHIFT; \
parent_rate >>= PARENT_RATE_SHIFT; \
diff = parent_rate; \
that seems to work. (Actually using the grandparent instead of a hard
coded &pll0_clk would be better.)
Can you please have a look, too and maybe even come up with a better
fix?
IMHO it's time that Jeremy's clk patches get merged to resolve the
uglinesses here. (One thing that comes to mind is that the result of
if (clk->parent == &ref_xtal_clk) doesn't change during runtime, so
it would be better to use two different implementations. (That
statement still needs a careful verification though.))
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply related
* [PATCH v4 0/4] davinci: add spi devices support for da8xx based platforms
From: Nori, Sekhar @ 2011-02-24 16:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298486651-18882-1-git-send-email-michael.williamson@criticallink.com>
Hi Mike,
On Thu, Feb 24, 2011 at 00:14:07, Michael Williamson wrote:
> This patch series adds SPI bus support and devices for the MityDSP-L138,
> MityARM-1808, da850 evm, and da830 evm platforms. This patch series is
> against the staging tree at [1] as per Sekhar's instructions.
>
> This series has been tested on the MityDSP-L138 platform.
I queued these patches for Kevin to pick-up for 2.6.39
Thanks for your efforts on this.
Best Regards,
Sekhar
^ permalink raw reply
* [PATCH V11 2/4] ptp: Added a clock that uses the eTSEC found on the MPC85xx.
From: Richard Cochran @ 2011-02-24 16:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110223132444.65dfdda4@schlenkerla>
On Wed, Feb 23, 2011 at 01:24:44PM -0600, Scott Wood wrote:
> Whatever string is used should be written into a binding document.
>
> fsl,etsec-v1.6-ptp seems like it would be just as good for that purpose.
>
> Even just fsl,etsec-ptp will identify the binding, though it's lacking in
> identifying the hardware (in the absence of access to the eTSEC ID
> registers).
I read the conversation, and I don't mind admitting that I do not
understand what you both are arguing/discussing about.
How should I set the strings? Like this?
arch/powerpc/boot/dts/mpc8313erdb.dts:
ptp_clock at 24E00 {
compatible = "fsl,mpc8313-etsec-ptp";
}
arch/powerpc/boot/dts/mpc8572ds.dts:
ptp_clock at 24E00 {
compatible = "fsl,mpc8572-etsec-ptp";
}
arch/powerpc/boot/dts/p2020ds.dts:
ptp_clock at 24E00 {
compatible = "fsl,p2020ds-etsec-ptp";
}
arch/powerpc/boot/dts/p2020rdb.dts:
ptp_clock at 24E00 {
compatible = "fsl,p2020rdb-etsec-ptp";
}
drivers/net/gianfar_ptp.c:
static struct of_device_id match_table[] = {
{ .compatible = "fsl,mpc8313-etsec-ptp" },
{ .compatible = "fsl,mpc8572-etsec-ptp" },
{ .compatible = "fsl,p2020ds-etsec-ptp" },
{ .compatible = "fsl,p2020rdb-etsec-ptp" },
{},
};
Please let me know if this is what you meant.
Thanks,
Richard
^ permalink raw reply
* [PATCH V11 2/4] ptp: Added a clock that uses the eTSEC found on the MPC85xx.
From: Richard Cochran @ 2011-02-24 16:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110223175459.GH14597@angua.secretlab.ca>
On Wed, Feb 23, 2011 at 10:54:59AM -0700, Grant Likely wrote:
> On Wed, Feb 23, 2011 at 11:26:12AM -0600, Scott Wood wrote:
> > The eTSEC revision is probeable as well, but due the way PTP is described as
> > a separate node, the driver doesn't have straightforward access to those
> > registers.
>
> Ignorant question: Should the ptp be described as a separate node?
Well, the PTP Hardware Clock function is logically separate from the
MAC function. PHCs can be implemented in the MAC, in the PHY, or in
between in an FPGA on MII bus.
If the PHC is in the MAC, then it might be wise to implement one
driver that offers both the MAC and the PHC.
In the case of gianfar, it is not really necessary to combine the PHC
into the gianfar driver, since the registers are pretty well
separated. Also, given the size and complexity (and churn over time)
of the gianfar driver, I decided to keep the PHC separate.
Right now, the driver correctly handles all the clock revisions in the
boards that I have (mpc8313, mpc8572, p2020ds, p2020rdb).
If checking the revision becomes important, then we can always export
a function from gianfar to provide this.
Thanks,
Richard
^ permalink raw reply
* [PATCH] omap: wd_timer: Fix crash frm wdt_probe when !CONFIG_RUNTIME_PM
From: Sricharan R @ 2011-02-24 16:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <007049e3361a3c4d0e7d2cfa105e2e67@mail.gmail.com>
Hi paul,
>-----Original Message-----
From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
>owner at vger.kernel.org] On Behalf Of Santosh Shilimkar
>Sent: Monday, January 17, 2011 10:09 PM
>To: Paul Walmsley
>Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
>Subject: RE: [PATCH] omap: wd_timer: Fix crash frm wdt_probe when
>!CONFIG_RUNTIME_PM
>
>> -----Original Message-----
>> From: Paul Walmsley [mailto:paul at pwsan.com]
>> Sent: Thursday, January 06, 2011 11:56 PM
>> To: Santosh Shilimkar
>> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
>> Subject: Re: [PATCH] omap: wd_timer: Fix crash frm wdt_probe when
>> !CONFIG_RUNTIME_PM
>>
>> Hi Santosh,
>>
>> On Wed, 5 Jan 2011, Santosh Shilimkar wrote:
>>
>> > Commit ff2516fb 'wd_timer: disable on boot via hwmod postsetup
>> mechanism'
>> > introduced watchdog timer state state management using
>> postsetup_state.
>> > This was done to allow some board files to support watchdog
>> coverage
>> > throughout kernel initialization and it work as intended when
>> RUNTIME_PM
>> > is enabled.
>> >
>> > With !CONFIG_RUNTIME_PM and no board is specifically requests
>> watchdog
>> > to remain enabled the omap_wdt_probe crashesh. This is because
>> hwmod
>> > in absense of runtime PM unable to turn watchdog clocks because
>> it's
>> > state is set to be disabled. For rest of the device, the state is
>> > set as enabled in absense of RUNTIME_PM
>> >
>> > [ 1.372558] Unhandled fault: imprecise external abort (0x1406)
>> at 0xad733eeb
>> > [ 1.379913] Internal error: : 1406 [#1] SMP
>> > [ 1.384277] last sysfs file:
>> > [ 1.387359] Modules linked in:
>> > [ 1.390563] CPU: 0 Tainted: G W (2.6.37-rc7-00265-
>> g4298a4c-dirty #23)
>> > [ 1.398468] PC is at omap_wdt_disable+0x2c/0x3c
>> > [ 1.403198] LR is at omap_wdt_probe+0x124/0x1e0
>> > [ 1.407928] pc : [<c02f5bf4>] lr : [<c03be10c>] psr:
>> 60000013
>> > [ 1.407958] sp : df833f00 ip : 00000000 fp : 00000000
>> > [ 1.419921] r10: c0ac57ac r9 : df959e00 r8 : 00000000
>> > [ 1.425384] r7 : df959e08 r6 : df8000c0 r5 : df95bebc r4 :
>> df87dde0
>> > [ 1.432189] r3 : fc314000 r2 : 00005555 r1 : fc314034 r0 :
>> df87dde0
>> >
>> > This patch make the default watchdog state to be enabled in case
>> of
>> > !CONFIG_RUNTIME_PM. This fixes the crash
>> >
>> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> > Cc: Paul Walmsley <paul@pwsan.com>
>> > ---
>> > Paul, I am not too sure if it breaks your _shutdown idea of
>> watchdog
>> > timer.
>>
>> Maybe. What happens in a case where the bootloader enables the
>> watchdog,
>> but the booting kernel is compiled with !CONFIG_OMAP_WATCHDOG and
>> !CONFIG_PM_RUNTIME? Won't the watchdog reset the MPU unexpectedly
>> in that
>> case? Or am I missing something...
>>
>I tried this scenario and some how the WDT isn't reseting MPU with my
>patch.
>
>Actually I was expecting it should reset but it didn't.
>
>Regards,
>Santosh
In the case of !CONFIG_PM_RUNTIME and !CONFIG_OMAP_WATCHDOG, if
the boot loader or hwmod enables the watchdog, then it generates
an un wanted reset.
So to avoid this in the case of !CONFIG_OMAP_WATCHDOG then the
watchdog should always be disabled.
So there are two cases:
Case 1: (!CONFIG_OMAP_WATCHDOG and !CONFIG_PM_RUNTIME)
Watchdog should be disabled.
Case 2: (!CONFIG_PM_RUNTIME) and ( driver is present and board file
enables it)
Watchdog should run.
Solution1:
Introduce a new hwmod watchdog reset function, by populating
the .reset entry of the hwmod.
This function is called during the hwmod init.
This function resets the watchdog always and also
disables it if !CONFIG_OMAP_WATCHDOG.
( or )
Solution2:
Introduce a state variable to differentiate if
hwmod post_setup_state is set to enabled by
by board file or io.c file.
Use this state variable in the reset function as
If it is enabled by io.c then disable watchdog
Otherwise if it is set to enabled by board file
then enable watchdog.
The below is the patch for solution1, that I have mentioned.
Please suggest which would be the right approach ?
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 657f3c8..2641d73 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -382,24 +382,6 @@ void __init omap2_init_common_infrastructure(void)
#endif
omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state);
- /*
- * Set the default postsetup state for unusual modules (like
- * MPU WDT).
- *
- * The postsetup_state is not actually used until
- * omap_hwmod_late_init(), so boards that desire full watchdog
- * coverage of kernel initialization can reprogram the
- * postsetup_state between the calls to
- * omap2_init_common_infra() and omap2_init_common_devices().
- *
- * XXX ideally we could detect whether the MPU WDT was currently
- * enabled here and make this conditional
- */
- postsetup_state = _HWMOD_STATE_DISABLED;
- omap_hwmod_for_each_by_class("wd_timer",
- _set_hwmod_postsetup_state,
- &postsetup_state);
-
omap_pm_if_early_init();
if (cpu_is_omap2420())
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 879f55f..d665ee5 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -545,7 +545,8 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
static struct omap_hwmod_class omap3xxx_wd_timer_hwmod_class = {
.name = "wd_timer",
.sysc = &omap3xxx_wd_timer_sysc,
- .pre_shutdown = &omap2_wd_timer_disable
+ .pre_shutdown = &omap2_wd_timer_disable,
+ .reset = &omap2_wd_timer_reset
};
/* wd_timer2 */
diff --git a/arch/arm/mach-omap2/wd_timer.c
b/arch/arm/mach-omap2/wd_timer.c
index 4067669..e11c5f3 100644
--- a/arch/arm/mach-omap2/wd_timer.c
+++ b/arch/arm/mach-omap2/wd_timer.c
@@ -24,7 +24,8 @@
*/
#define OMAP_WDT_WPS 0x34
#define OMAP_WDT_SPR 0x48
-
+#define OMAP_WDT_DSC 0x10
+#define OMAP_WDT_DST 0x14
int omap2_wd_timer_disable(struct omap_hwmod *oh)
{
@@ -54,3 +55,32 @@ int omap2_wd_timer_disable(struct omap_hwmod *oh)
return 0;
}
+int omap2_wd_timer_reset(struct omap_hwmod *oh)
+{
+ void __iomem *base;
+ pr_err("\n\n\n\n\n\n\n\n\n omap2_wd_timer_reset \n\n\n\n\n");
+
+ if (!oh) {
+ pr_err("%s: could not look up wdtimer_hwmod\n",__func__);
+ }
+
+ base = omap_hwmod_get_mpu_rt_va(oh);
+ if(!base) {
+ pr_err("%s: Could not get the base address for %s\n",
+ oh->name, __func__);
+ return -EINVAL;
+ }
+
+ /* soft reset on watch dog timer */
+ __raw_writel(0x02, base + OMAP_WDT_DSC);
+ while (__raw_readl(base + OMAP_WDT_DST) & 0x1)
+ cpu_relax();
+
+#ifdef CONFIG_OMAP_WATCHDOG
+ /* Disable the watchdog */
+ omap2_wd_timer_disable(oh);
+#endif
+
+ return 0;
+}
+
diff --git a/arch/arm/mach-omap2/wd_timer.h
b/arch/arm/mach-omap2/wd_timer.h
index e0054a2..f6bbba7 100644
--- a/arch/arm/mach-omap2/wd_timer.h
+++ b/arch/arm/mach-omap2/wd_timer.h
@@ -13,5 +13,6 @@
#include <plat/omap_hwmod.h>
extern int omap2_wd_timer_disable(struct omap_hwmod *oh);
+extern int omap2_wd_timer_reset(struct omap_hwmod *oh);
Thanks,
Sricharan
----
>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 related
* [PATCH V3 0/5] sdhci-esdhc-imx: use gpio for write protection and card detection
From: Shawn Guo @ 2011-02-24 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110224155126.GA1466@S2100-06.ap.freescale.net>
On Thu, Feb 24, 2011 at 11:51:28PM +0800, Shawn Guo wrote:
> On Thu, Feb 24, 2011 at 04:18:05PM +0800, Shawn Guo wrote:
> > Hi Wolfram,
> >
> > On Wed, Feb 23, 2011 at 02:51:53PM +0100, Wolfram Sang wrote:
> > > Take #3, changes:
> > >
> > > * also intercept calls to SDHCI_SIGNAL_ENABLE (needed on mx25)
> > > * remove unconditional BROKEN_CARD_DETECTION (leftover)
> > > * improved kernel-doc about unused GPIO
> > > * added tags from Eric
> > >
> > > Tested now by me and Marc on mx35, Eric on mx25/35/51. Arnaud, did you have a
> > > chance to retest on mx51? What about the FSL guys? :)
> > >
> > I'm testing it on mx25 3ds and mx51 babbage. Both card-detect and
> > write-protect are working on mx25 3ds, but write-protect has some
> > problem on babbage, and I need some time to figure it out.
> >
> I just figured out why wp_gpio does not work on mx51.
>
> + if (cpu_is_mx25() || cpu_is_mx35()) {
> + /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
> host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
> + /* write_protect can't be routed to controller, use gpio */
> + sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
> + }
>
> Would it make sense to do the same for mx51? On babbage board,
> SD1_WP is routed to controller, but SD2_WP is not, so we have to use
> gpio for SD2 write_protect.
>
We should probably have esdhc_pltfm_get_ro whenever platform provides
a wp_gpio, and fall on controller SD_WP only when platform does not
provide the wp_gpio.
--
Regards,
Shawn
^ permalink raw reply
* [PATCH] ARM: plat-mxc: ehci: Fix inverted logic of OC bit
From: David Jander @ 2011-02-24 15:55 UTC (permalink / raw)
To: linux-arm-kernel
If MXC_EHCI_POWER_PINS_ENABLED is set, MXC_OTG_PHYCTRL_OC_DIS_BIT
must be cleared, not set.
Signed-off-by: David Jander <david@protonic.nl>
---
arch/arm/plat-mxc/ehci.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm/plat-mxc/ehci.c b/arch/arm/plat-mxc/ehci.c
index 8772ce3..5f01d9c 100644
--- a/arch/arm/plat-mxc/ehci.c
+++ b/arch/arm/plat-mxc/ehci.c
@@ -288,11 +288,11 @@ int mxc_initialize_usb_hw(int port, unsigned int flags)
v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
- /* OC/USBPWR is not used */
- v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
- } else {
/* OC/USBPWR is used */
v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
+ } else {
+ /* OC/USBPWR is not used */
+ v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
}
__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
--
1.7.0.4
^ permalink raw reply related
* [PATCH V3 0/5] sdhci-esdhc-imx: use gpio for write protection and card detection
From: Shawn Guo @ 2011-02-24 15:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110224081803.GA29530@S2100-06.ap.freescale.net>
On Thu, Feb 24, 2011 at 04:18:05PM +0800, Shawn Guo wrote:
> Hi Wolfram,
>
> On Wed, Feb 23, 2011 at 02:51:53PM +0100, Wolfram Sang wrote:
> > Take #3, changes:
> >
> > * also intercept calls to SDHCI_SIGNAL_ENABLE (needed on mx25)
> > * remove unconditional BROKEN_CARD_DETECTION (leftover)
> > * improved kernel-doc about unused GPIO
> > * added tags from Eric
> >
> > Tested now by me and Marc on mx35, Eric on mx25/35/51. Arnaud, did you have a
> > chance to retest on mx51? What about the FSL guys? :)
> >
> I'm testing it on mx25 3ds and mx51 babbage. Both card-detect and
> write-protect are working on mx25 3ds, but write-protect has some
> problem on babbage, and I need some time to figure it out.
>
I just figured out why wp_gpio does not work on mx51.
+ if (cpu_is_mx25() || cpu_is_mx35()) {
+ /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+ /* write_protect can't be routed to controller, use gpio */
+ sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
+ }
Would it make sense to do the same for mx51? On babbage board,
SD1_WP is routed to controller, but SD2_WP is not, so we have to use
gpio for SD2 write_protect.
--
Regards,
Shawn
^ permalink raw reply
* [PATCH 5/5] ARM: msm: update GPIO chained IRQ handler to use EOI in parent chip
From: Thomas Gleixner @ 2011-02-24 15:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <000401cbd42c$e9a957b0$bcfc0710$@deacon@arm.com>
On Thu, 24 Feb 2011, Will Deacon wrote:
> > On Wed, 23 Feb 2011, Abhijeet Dharmapurikar wrote:
>
> Something like this?
>
> diff --git a/arch/arm/mach-msm/gpio-v2.c b/arch/arm/mach-msm/gpio-v2.c
> index 0de19ec..90a968f 100644
> --- a/arch/arm/mach-msm/gpio-v2.c
> +++ b/arch/arm/mach-msm/gpio-v2.c
> @@ -310,6 +310,7 @@ static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
> static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
> {
> unsigned long i;
> + struct irq_chip *chip = get_irq_desc_chip(desc);
>
> for (i = find_first_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS);
> i < NR_GPIO_IRQS;
> @@ -318,7 +319,7 @@ static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
> generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
> i));
> }
> - desc->chip->ack(irq);
> + chip->irq_eoi(&desc->irq_data);
Yep. Thanks,
tglx
>
^ permalink raw reply
* [PATCH 8/8] OMAP2+: clockevent: late-init GPTIMER clockevent hwmodright before timer init
From: Tony Lindgren @ 2011-02-24 15:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5A47E75E594F054BAF48C5E4FC4B92AB037A0958B7@dbde02.ent.ti.com>
* DebBarma, Tarun Kanti <tarun.kanti@ti.com> [110224 00:27]:
> I have tested on OMAP3 and works fine.
> On OMAP2, I guess there is different issue for which it does not work.
That's because commit 15490ef8ff8fd22d677cb5d4f6a98e5a79118dba changed
things to include CONFIG_CPU_32v6K. And this means that omap-for-linus
won't boot on omap2 currently using omap2plus_defconfig. The master
branch boots because of the patches in omap-testing.
To boot test omap-for-linus, you can temporarily merge in the
omap-testing branch that has the pending patches from Russell to
make non-6K ARMv6 processors work with CONFIG_CPU_32v6K.
Regards,
Tony
^ permalink raw reply
* [PATCH] kbuild: reenable section mismatch analysis
From: Michal Marek @ 2011-02-24 15:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298062040-2774-1-git-send-email-u.kleine-koenig@pengutronix.de>
On 18.2.2011 21:47, Uwe Kleine-K?nig wrote:
> This was disabled in commit
>
> e5f95c8 (kbuild: print only total number of section mismatces found)
>
> because there were too many warnings. Now we're down to a reasonable
> number again, so we start scaring people with the details.
>
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
OK, applied to kbuild-2.6.git#kbuild.
Thanks,
Michal
^ permalink raw reply
* [PATCH] OMAP4: clock: Support divider selection for auxclks
From: Rajendra Nayak @ 2011-02-24 14:28 UTC (permalink / raw)
To: linux-arm-kernel
On OMAP4 the auxclk nodes (part of SCRM) support both
divider as well as parent selection.
Supporting this requires splitting the existing nodes
(which support only parent selection) into
two nodes, one for parent and another for
divider selection.
The nodes for parent selection are named
auxclk*_src_ck and the ones for divider
selection as auxclk*_ck
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Tested-by: Anand Gadiyar <gadiyar@ti.com>
---
The only user of these auxclks' today is
USB PHY on panda board.
Thanks to Anand G for testing this works
fine with the patch,
Patch is based on 2.6.38-rc6 kernel.
arch/arm/mach-omap2/clock44xx_data.c | 179 +++++++++++++++++++++++++++++-----
1 files changed, 154 insertions(+), 25 deletions(-)
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index de9ec8d..af1aa93 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -2842,19 +2842,39 @@ static struct clk trace_clk_div_ck = {
/* SCRM aux clk nodes */
-static const struct clksel auxclk_sel[] = {
+static const struct clksel auxclk_src_sel[] = {
{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
{ .parent = &dpll_core_m3x2_ck, .rates = div_1_1_rates },
{ .parent = &dpll_per_m3x2_ck, .rates = div_1_2_rates },
{ .parent = NULL },
};
-static struct clk auxclk0_ck = {
- .name = "auxclk0_ck",
+static const struct clksel_rate div16_1to16_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_4430 },
+ { .div = 2, .val = 1, .flags = RATE_IN_4430 },
+ { .div = 3, .val = 2, .flags = RATE_IN_4430 },
+ { .div = 4, .val = 3, .flags = RATE_IN_4430 },
+ { .div = 5, .val = 4, .flags = RATE_IN_4430 },
+ { .div = 6, .val = 5, .flags = RATE_IN_4430 },
+ { .div = 7, .val = 6, .flags = RATE_IN_4430 },
+ { .div = 8, .val = 7, .flags = RATE_IN_4430 },
+ { .div = 9, .val = 8, .flags = RATE_IN_4430 },
+ { .div = 10, .val = 9, .flags = RATE_IN_4430 },
+ { .div = 11, .val = 10, .flags = RATE_IN_4430 },
+ { .div = 12, .val = 11, .flags = RATE_IN_4430 },
+ { .div = 13, .val = 12, .flags = RATE_IN_4430 },
+ { .div = 14, .val = 13, .flags = RATE_IN_4430 },
+ { .div = 15, .val = 14, .flags = RATE_IN_4430 },
+ { .div = 16, .val = 15, .flags = RATE_IN_4430 },
+ { .div = 0 },
+};
+
+static struct clk auxclk0_src_ck = {
+ .name = "auxclk0_src_ck",
.parent = &sys_clkin_ck,
.init = &omap2_init_clksel_parent,
.ops = &clkops_omap2_dflt,
- .clksel = auxclk_sel,
+ .clksel = auxclk_src_sel,
.clksel_reg = OMAP4_SCRM_AUXCLK0,
.clksel_mask = OMAP4_SRCSELECT_MASK,
.recalc = &omap2_clksel_recalc,
@@ -2862,12 +2882,29 @@ static struct clk auxclk0_ck = {
.enable_bit = OMAP4_ENABLE_SHIFT,
};
-static struct clk auxclk1_ck = {
- .name = "auxclk1_ck",
+static const struct clksel auxclk0_sel[] = {
+ { .parent = &auxclk0_src_ck, .rates = div16_1to16_rates },
+ { .parent = NULL },
+};
+
+static struct clk auxclk0_ck = {
+ .name = "auxclk0_ck",
+ .parent = &auxclk0_src_ck,
+ .clksel = auxclk0_sel,
+ .clksel_reg = OMAP4_SCRM_AUXCLK0,
+ .clksel_mask = OMAP4_CLKDIV_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk1_src_ck = {
+ .name = "auxclk1_src_ck",
.parent = &sys_clkin_ck,
.init = &omap2_init_clksel_parent,
.ops = &clkops_omap2_dflt,
- .clksel = auxclk_sel,
+ .clksel = auxclk_src_sel,
.clksel_reg = OMAP4_SCRM_AUXCLK1,
.clksel_mask = OMAP4_SRCSELECT_MASK,
.recalc = &omap2_clksel_recalc,
@@ -2875,24 +2912,59 @@ static struct clk auxclk1_ck = {
.enable_bit = OMAP4_ENABLE_SHIFT,
};
-static struct clk auxclk2_ck = {
- .name = "auxclk2_ck",
+static const struct clksel auxclk1_sel[] = {
+ { .parent = &auxclk1_src_ck, .rates = div16_1to16_rates },
+ { .parent = NULL },
+};
+
+static struct clk auxclk1_ck = {
+ .name = "auxclk1_ck",
+ .parent = &auxclk1_src_ck,
+ .clksel = auxclk1_sel,
+ .clksel_reg = OMAP4_SCRM_AUXCLK1,
+ .clksel_mask = OMAP4_CLKDIV_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk2_src_ck = {
+ .name = "auxclk2_src_ck",
.parent = &sys_clkin_ck,
.init = &omap2_init_clksel_parent,
.ops = &clkops_omap2_dflt,
- .clksel = auxclk_sel,
+ .clksel = auxclk_src_sel,
.clksel_reg = OMAP4_SCRM_AUXCLK2,
.clksel_mask = OMAP4_SRCSELECT_MASK,
.recalc = &omap2_clksel_recalc,
.enable_reg = OMAP4_SCRM_AUXCLK2,
.enable_bit = OMAP4_ENABLE_SHIFT,
};
-static struct clk auxclk3_ck = {
- .name = "auxclk3_ck",
+
+static const struct clksel auxclk2_sel[] = {
+ { .parent = &auxclk2_src_ck, .rates = div16_1to16_rates },
+ { .parent = NULL },
+};
+
+static struct clk auxclk2_ck = {
+ .name = "auxclk2_ck",
+ .parent = &auxclk2_src_ck,
+ .clksel = auxclk2_sel,
+ .clksel_reg = OMAP4_SCRM_AUXCLK2,
+ .clksel_mask = OMAP4_CLKDIV_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk3_src_ck = {
+ .name = "auxclk3_src_ck",
.parent = &sys_clkin_ck,
.init = &omap2_init_clksel_parent,
.ops = &clkops_omap2_dflt,
- .clksel = auxclk_sel,
+ .clksel = auxclk_src_sel,
.clksel_reg = OMAP4_SCRM_AUXCLK3,
.clksel_mask = OMAP4_SRCSELECT_MASK,
.recalc = &omap2_clksel_recalc,
@@ -2900,12 +2972,29 @@ static struct clk auxclk3_ck = {
.enable_bit = OMAP4_ENABLE_SHIFT,
};
-static struct clk auxclk4_ck = {
- .name = "auxclk4_ck",
+static const struct clksel auxclk3_sel[] = {
+ { .parent = &auxclk3_src_ck, .rates = div16_1to16_rates },
+ { .parent = NULL },
+};
+
+static struct clk auxclk3_ck = {
+ .name = "auxclk3_ck",
+ .parent = &auxclk3_src_ck,
+ .clksel = auxclk3_sel,
+ .clksel_reg = OMAP4_SCRM_AUXCLK3,
+ .clksel_mask = OMAP4_CLKDIV_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk4_src_ck = {
+ .name = "auxclk4_src_ck",
.parent = &sys_clkin_ck,
.init = &omap2_init_clksel_parent,
.ops = &clkops_omap2_dflt,
- .clksel = auxclk_sel,
+ .clksel = auxclk_src_sel,
.clksel_reg = OMAP4_SCRM_AUXCLK4,
.clksel_mask = OMAP4_SRCSELECT_MASK,
.recalc = &omap2_clksel_recalc,
@@ -2913,12 +3002,29 @@ static struct clk auxclk4_ck = {
.enable_bit = OMAP4_ENABLE_SHIFT,
};
-static struct clk auxclk5_ck = {
- .name = "auxclk5_ck",
+static const struct clksel auxclk4_sel[] = {
+ { .parent = &auxclk4_src_ck, .rates = div16_1to16_rates },
+ { .parent = NULL },
+};
+
+static struct clk auxclk4_ck = {
+ .name = "auxclk4_ck",
+ .parent = &auxclk4_src_ck,
+ .clksel = auxclk4_sel,
+ .clksel_reg = OMAP4_SCRM_AUXCLK4,
+ .clksel_mask = OMAP4_CLKDIV_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk5_src_ck = {
+ .name = "auxclk5_src_ck",
.parent = &sys_clkin_ck,
.init = &omap2_init_clksel_parent,
.ops = &clkops_omap2_dflt,
- .clksel = auxclk_sel,
+ .clksel = auxclk_src_sel,
.clksel_reg = OMAP4_SCRM_AUXCLK5,
.clksel_mask = OMAP4_SRCSELECT_MASK,
.recalc = &omap2_clksel_recalc,
@@ -2926,6 +3032,23 @@ static struct clk auxclk5_ck = {
.enable_bit = OMAP4_ENABLE_SHIFT,
};
+static const struct clksel auxclk5_sel[] = {
+ { .parent = &auxclk5_src_ck, .rates = div16_1to16_rates },
+ { .parent = NULL },
+};
+
+static struct clk auxclk5_ck = {
+ .name = "auxclk5_ck",
+ .parent = &auxclk5_src_ck,
+ .clksel = auxclk5_sel,
+ .clksel_reg = OMAP4_SCRM_AUXCLK5,
+ .clksel_mask = OMAP4_CLKDIV_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
static const struct clksel auxclkreq_sel[] = {
{ .parent = &auxclk0_ck, .rates = div_1_0_rates },
{ .parent = &auxclk1_ck, .rates = div_1_1_rates },
@@ -3263,12 +3386,18 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "uart3_ick", &dummy_ck, CK_443X),
CLK(NULL, "uart4_ick", &dummy_ck, CK_443X),
CLK("omap_wdt", "ick", &dummy_ck, CK_443X),
- CLK(NULL, "auxclk0_ck", &auxclk0_ck, CK_443X),
- CLK(NULL, "auxclk1_ck", &auxclk1_ck, CK_443X),
- CLK(NULL, "auxclk2_ck", &auxclk2_ck, CK_443X),
- CLK(NULL, "auxclk3_ck", &auxclk3_ck, CK_443X),
- CLK(NULL, "auxclk4_ck", &auxclk4_ck, CK_443X),
- CLK(NULL, "auxclk5_ck", &auxclk5_ck, CK_443X),
+ CLK(NULL, "auxclk0_src_ck", &auxclk0_src_ck, CK_443X),
+ CLK(NULL, "auxclk0_ck", &auxclk0_ck, CK_443X),
+ CLK(NULL, "auxclk1_src_ck", &auxclk1_src_ck, CK_443X),
+ CLK(NULL, "auxclk1_ck", &auxclk1_ck, CK_443X),
+ CLK(NULL, "auxclk2_src_ck", &auxclk2_src_ck, CK_443X),
+ CLK(NULL, "auxclk2_ck", &auxclk2_ck, CK_443X),
+ CLK(NULL, "auxclk3_src_ck", &auxclk3_src_ck, CK_443X),
+ CLK(NULL, "auxclk3_ck", &auxclk3_ck, CK_443X),
+ CLK(NULL, "auxclk4_src_ck", &auxclk4_src_ck, CK_443X),
+ CLK(NULL, "auxclk4_ck", &auxclk4_ck, CK_443X),
+ CLK(NULL, "auxclk5_src_ck", &auxclk5_src_ck, CK_443X),
+ CLK(NULL, "auxclk5_ck", &auxclk5_ck, CK_443X),
CLK(NULL, "auxclkreq0_ck", &auxclkreq0_ck, CK_443X),
CLK(NULL, "auxclkreq1_ck", &auxclkreq1_ck, CK_443X),
CLK(NULL, "auxclkreq2_ck", &auxclkreq2_ck, CK_443X),
--
1.7.0.4
^ permalink raw reply related
* [PATCH v4 1/2] PRUSS UIO driver support
From: Thomas Gleixner @ 2011-02-24 14:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298556402-26456-2-git-send-email-pratheesh@ti.com>
On Thu, 24 Feb 2011, Pratheesh Gangadhar wrote:
A few nits.
> +static void pruss_cleanup(struct platform_device *dev, struct uio_info *info)
> +{
> + struct uio_info *p = info;
> + int cnt;
> +
> + for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) {
> + uio_unregister_device(p);
> + kfree(p->name);
> + }
> + iounmap(prussio_vaddr);
> + if (ddr_vaddr)
> + dma_free_coherent(&dev->dev, info->mem[2].size,
> + info->mem[2].internal_addr, info->mem[2].addr);
That is easier to read with curly braces even if they are strictly not
necessary
if (ddr_vaddr) {
dma_free_coherent(&dev->dev, info->mem[2].size,
info->mem[2].internal_addr, info->mem[2].addr);
}
> + kfree(info);
> + clk_put(pruss_clk);
> +}
> + len = resource_size(regs_ddr);
> + ddr_vaddr =
> + dma_alloc_coherent(&dev->dev, len, &ddr_paddr, GFP_KERNEL | GFP_DMA);
That wants to be:
ddr_vaddr = dma_alloc_coherent(&dev->dev, len, &ddr_paddr,
GFP_KERNEL | GFP_DMA);
Otherwise this looks very clean and readable now and I can't spot any
technical problems with it anymore.
Please fixup the nits and feel free to add
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Thanks for following up on all this!
tglx
^ permalink raw reply
* [PATCH 5/5] ARM: msm: update GPIO chained IRQ handler to use EOI in parent chip
From: Will Deacon @ 2011-02-24 14:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.00.1102241338410.2701@localhost6.localdomain6>
> On Wed, 23 Feb 2011, Abhijeet Dharmapurikar wrote:
>
> > Will Deacon wrote:
> > > The chained GPIO IRQ handler on MSM8x60 calls ->ack on the parent chip
> > > after handling the interrupt.
> > >
> > > This patch updates the code to use ->irq_eoi now that the GIC has moved
> > > to using the fasteoi flow model.
> > >
> > > Cc: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> > > Signed-off-by: Will Deacon <will.deacon@arm.com>
> > > ---
> > > arch/arm/mach-msm/gpio-v2.c | 2 +-
> > > 1 files changed, 1 insertions(+), 1 deletions(-)
> > >
> > > diff --git a/arch/arm/mach-msm/gpio-v2.c b/arch/arm/mach-msm/gpio-v2.c
> > > index 0de19ec..04fb411 100644
> > > --- a/arch/arm/mach-msm/gpio-v2.c
> > > +++ b/arch/arm/mach-msm/gpio-v2.c
> > > @@ -318,7 +318,7 @@ static void msm_summary_irq_handler(unsigned int irq,
> > > struct irq_desc *desc)
> > > generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
> > > i));
> > > }
> > > - desc->chip->ack(irq);
> > > + desc->chip->irq_eoi(irq);
> >
> > should be dec->chip->irq_eoi(&desc->irq_data);
>
> Nope, it should do:
>
> struct irq_chip *chip = get_irq_desc_chip(desc);
>
> chip->irq_eoi();
Something like this?
diff --git a/arch/arm/mach-msm/gpio-v2.c b/arch/arm/mach-msm/gpio-v2.c
index 0de19ec..90a968f 100644
--- a/arch/arm/mach-msm/gpio-v2.c
+++ b/arch/arm/mach-msm/gpio-v2.c
@@ -310,6 +310,7 @@ static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
{
unsigned long i;
+ struct irq_chip *chip = get_irq_desc_chip(desc);
for (i = find_first_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS);
i < NR_GPIO_IRQS;
@@ -318,7 +319,7 @@ static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
i));
}
- desc->chip->ack(irq);
+ chip->irq_eoi(&desc->irq_data);
}
Will
^ permalink raw reply related
* [PATCH v4 2/2] Defines DA850/AM18xx/OMAPL1-38 SOC resources used by PRUSS UIO driver
From: Pratheesh Gangadhar @ 2011-02-24 14:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298556402-26456-2-git-send-email-pratheesh@ti.com>
This patch defines PRUSS, ECAP clocks, memory and IRQ resources
used by PRUSS UIO driver in DA850/AM18xx/OMAPL1-38 devices. UIO
driver exports 64K I/O region of PRUSS, 128KB L3 RAM and 256KB
DDR buffer to user space. PRUSS has 8 host event interrupt lines
mapped to IRQ_DA8XX_EVTOUT0..7 of ARM9 INTC.These in conjunction
with shared memory can be used to implement IPC between ARM9 and
PRUSS.
Signed-off-by: Pratheesh Gangadhar <pratheesh@ti.com>
---
arch/arm/mach-davinci/board-da850-evm.c | 4 ++
arch/arm/mach-davinci/da850.c | 35 +++++++++++++
arch/arm/mach-davinci/devices-da8xx.c | 73 ++++++++++++++++++++++++++++
arch/arm/mach-davinci/include/mach/da8xx.h | 3 +
4 files changed, 115 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 11f986b..bd85aa3 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1077,6 +1077,10 @@ static __init void da850_evm_init(void)
pr_warning("da850_evm_init: i2c0 registration failed: %d\n",
ret);
+ ret = da8xx_register_pruss();
+ if (ret)
+ pr_warning("da850_evm_init: pruss registration failed: %d\n",
+ ret);
ret = da8xx_register_watchdog();
if (ret)
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 3443d97..0096d4f 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -238,6 +238,13 @@ static struct clk tptc2_clk = {
.flags = ALWAYS_ENABLED,
};
+static struct clk pruss_clk = {
+ .name = "pruss",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA8XX_LPSC0_DMAX,
+ .flags = ALWAYS_ENABLED,
+};
+
static struct clk uart0_clk = {
.name = "uart0",
.parent = &pll0_sysclk2,
@@ -359,6 +366,30 @@ static struct clk usb20_clk = {
.gpsc = 1,
};
+static struct clk ecap0_clk = {
+ .name = "ecap0",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA8XX_LPSC1_ECAP,
+ .flags = DA850_CLK_ASYNC3,
+ .gpsc = 1,
+};
+
+static struct clk ecap1_clk = {
+ .name = "ecap1",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA8XX_LPSC1_ECAP,
+ .flags = DA850_CLK_ASYNC3,
+ .gpsc = 1,
+};
+
+static struct clk ecap2_clk = {
+ .name = "ecap2",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA8XX_LPSC1_ECAP,
+ .flags = DA850_CLK_ASYNC3,
+ .gpsc = 1,
+};
+
static struct clk_lookup da850_clks[] = {
CLK(NULL, "ref", &ref_clk),
CLK(NULL, "pll0", &pll0_clk),
@@ -386,6 +417,7 @@ static struct clk_lookup da850_clks[] = {
CLK(NULL, "tptc1", &tptc1_clk),
CLK(NULL, "tpcc1", &tpcc1_clk),
CLK(NULL, "tptc2", &tptc2_clk),
+ CLK(NULL, "pruss", &pruss_clk),
CLK(NULL, "uart0", &uart0_clk),
CLK(NULL, "uart1", &uart1_clk),
CLK(NULL, "uart2", &uart2_clk),
@@ -403,6 +435,9 @@ static struct clk_lookup da850_clks[] = {
CLK(NULL, "aemif", &aemif_clk),
CLK(NULL, "usb11", &usb11_clk),
CLK(NULL, "usb20", &usb20_clk),
+ CLK(NULL, "ecap0", &ecap0_clk),
+ CLK(NULL, "ecap1", &ecap1_clk),
+ CLK(NULL, "ecap2", &ecap2_clk),
CLK(NULL, NULL, NULL),
};
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index beda8a4..4ea3d1f 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -725,3 +725,76 @@ int __init da8xx_register_cpuidle(void)
return platform_device_register(&da8xx_cpuidle_device);
}
+static struct resource pruss_resources[] = {
+ [0] = {
+ .start = DA8XX_PRUSS_BASE,
+ .end = DA8XX_PRUSS_BASE + SZ_64K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DA8XX_L3RAM_BASE,
+ .end = DA8XX_L3RAM_BASE + SZ_128K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 0,
+ .end = SZ_256K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ [3] = {
+ .start = IRQ_DA8XX_EVTOUT0,
+ .end = IRQ_DA8XX_EVTOUT0,
+ .flags = IORESOURCE_IRQ,
+ },
+ [4] = {
+ .start = IRQ_DA8XX_EVTOUT1,
+ .end = IRQ_DA8XX_EVTOUT1,
+ .flags = IORESOURCE_IRQ,
+ },
+ [5] = {
+ .start = IRQ_DA8XX_EVTOUT2,
+ .end = IRQ_DA8XX_EVTOUT2,
+ .flags = IORESOURCE_IRQ,
+ },
+ [6] = {
+ .start = IRQ_DA8XX_EVTOUT3,
+ .end = IRQ_DA8XX_EVTOUT3,
+ .flags = IORESOURCE_IRQ,
+ },
+ [7] = {
+ .start = IRQ_DA8XX_EVTOUT4,
+ .end = IRQ_DA8XX_EVTOUT4,
+ .flags = IORESOURCE_IRQ,
+ },
+ [8] = {
+ .start = IRQ_DA8XX_EVTOUT5,
+ .end = IRQ_DA8XX_EVTOUT5,
+ .flags = IORESOURCE_IRQ,
+ },
+ [9] = {
+ .start = IRQ_DA8XX_EVTOUT6,
+ .end = IRQ_DA8XX_EVTOUT6,
+ .flags = IORESOURCE_IRQ,
+ },
+ [10] = {
+ .start = IRQ_DA8XX_EVTOUT7,
+ .end = IRQ_DA8XX_EVTOUT7,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device pruss_device = {
+ .name = "pruss",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(pruss_resources),
+ .resource = pruss_resources,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ }
+};
+
+int __init da8xx_register_pruss()
+{
+ return platform_device_register(&pruss_device);
+}
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index cfcb223..3ed6ee0 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -60,6 +60,7 @@ extern unsigned int da850_max_speed;
#define DA8XX_PLL0_BASE 0x01c11000
#define DA8XX_TIMER64P0_BASE 0x01c20000
#define DA8XX_TIMER64P1_BASE 0x01c21000
+#define DA8XX_PRUSS_BASE 0x01c30000
#define DA8XX_GPIO_BASE 0x01e26000
#define DA8XX_PSC1_BASE 0x01e27000
#define DA8XX_LCD_CNTRL_BASE 0x01e13000
@@ -68,6 +69,7 @@ extern unsigned int da850_max_speed;
#define DA8XX_AEMIF_CS2_BASE 0x60000000
#define DA8XX_AEMIF_CS3_BASE 0x62000000
#define DA8XX_AEMIF_CTL_BASE 0x68000000
+#define DA8XX_L3RAM_BASE 0x80000000
#define DA8XX_DDR2_CTL_BASE 0xb0000000
#define DA8XX_ARM_RAM_BASE 0xffff0000
@@ -90,6 +92,7 @@ int da850_register_cpufreq(char *async_clk);
int da8xx_register_cpuidle(void);
void __iomem * __init da8xx_get_mem_ctlr(void);
int da850_register_pm(struct platform_device *pdev);
+int da8xx_register_pruss(void);
extern struct platform_device da8xx_serial_device;
extern struct emac_platform_data da8xx_emac_pdata;
--
1.6.0.6
^ permalink raw reply related
* [PATCH v4 1/2] PRUSS UIO driver support
From: Pratheesh Gangadhar @ 2011-02-24 14:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298556402-26456-1-git-send-email-pratheesh@ti.com>
This patch implements PRUSS (Programmable Real-time Unit Sub System)
UIO driver which exports SOC resources associated with PRUSS like
I/O, memories and IRQs to user space. PRUSS is dual 32-bit RISC
processors which is efficient in performing embedded tasks that
require manipulation of packed memory mapped data structures and
efficient in handling system events that have tight real time
constraints. This driver is currently supported on Texas Instruments
DA850, AM18xx and OMAPL1-38 devices.
For example, PRUSS runs firmware for real-time critical industrial
communication data link layer and communicates with application stack
running in user space via shared memory and IRQs.
Signed-off-by: Pratheesh Gangadhar <pratheesh@ti.com>
---
drivers/uio/Kconfig | 17 ++++
drivers/uio/Makefile | 1 +
drivers/uio/uio_pruss.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 234 insertions(+), 0 deletions(-)
create mode 100644 drivers/uio/uio_pruss.c
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index bb44079..6f3ea9b 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -94,4 +94,21 @@ config UIO_NETX
To compile this driver as a module, choose M here; the module
will be called uio_netx.
+config UIO_PRUSS
+ tristate "Texas Instruments PRUSS driver"
+ depends on ARCH_DAVINCI_DA850
+ help
+ PRUSS driver for OMAPL138/DA850/AM18XX devices
+ PRUSS driver requires user space components, examples and user space
+ driver is available from below SVN repo - you may use anonymous login
+
+ https://gforge.ti.com/gf/project/pru_sw/
+
+ More info on API is available at below wiki
+
+ http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader
+
+ To compile this driver as a module, choose M here: the module
+ will be called uio_pruss.
+
endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 18fd818..d4dd9a5 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_UIO_AEC) += uio_aec.o
obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
obj-$(CONFIG_UIO_NETX) += uio_netx.o
+obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
new file mode 100644
index 0000000..bb92941
--- /dev/null
+++ b/drivers/uio/uio_pruss.c
@@ -0,0 +1,216 @@
+/*
+ * Programmable Real-Time Unit Sub System (PRUSS) UIO driver (uio_pruss)
+ *
+ * This driver exports PRUSS host event out interrupts and PRUSS, L3 RAM,
+ * and DDR RAM to user space for applications interacting with PRUSS firmware
+ *
+ * Copyright (C) 2010-11 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/uio_driver.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#define DRV_NAME "pruss"
+#define DRV_VERSION "0.50"
+
+/*
+ * Host event IRQ numbers from PRUSS - PRUSS can generate upto 8 interrupt
+ * events to AINTC of ARM host processor - which can be used for IPC b/w PRUSS
+ * firmware and user space application, async notification from PRU firmware
+ * to user space application
+ * 3 PRU_EVTOUT0
+ * 4 PRU_EVTOUT1
+ * 5 PRU_EVTOUT2
+ * 6 PRU_EVTOUT3
+ * 7 PRU_EVTOUT4
+ * 8 PRU_EVTOUT5
+ * 9 PRU_EVTOUT6
+ * 10 PRU_EVTOUT7
+*/
+
+#define MAX_PRUSS_EVT 8
+
+#define PINTC_HIPIR 0x4900
+#define HIPIR_NOPEND 0x80000000
+#define PINTC_HIER 0x5500
+
+static struct clk *pruss_clk;
+static struct uio_info *info;
+static dma_addr_t ddr_paddr;
+static void *ddr_vaddr, *prussio_vaddr;
+
+static irqreturn_t pruss_handler(int irq, struct uio_info *dev_info)
+{
+ void __iomem *base = dev_info->mem[0].internal_addr;
+ void __iomem *intren_reg = base + PINTC_HIER;
+ void __iomem *intrstat_reg = base + PINTC_HIPIR + ((irq - 1) << 2);
+ int val = ioread32(intren_reg), intr_mask = (1 << (irq - 1));
+
+ /* Is interrupt enabled and active ? */
+ if (!(val & intr_mask) && (ioread32(intrstat_reg) & HIPIR_NOPEND))
+ return IRQ_NONE;
+
+ /* Disable interrupt */
+ iowrite32((val & ~intr_mask), intren_reg);
+ return IRQ_HANDLED;
+}
+
+static void pruss_cleanup(struct platform_device *dev, struct uio_info *info)
+{
+ struct uio_info *p = info;
+ int cnt;
+
+ for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) {
+ uio_unregister_device(p);
+ kfree(p->name);
+ }
+ iounmap(prussio_vaddr);
+ if (ddr_vaddr)
+ dma_free_coherent(&dev->dev, info->mem[2].size,
+ info->mem[2].internal_addr, info->mem[2].addr);
+ kfree(info);
+ clk_put(pruss_clk);
+}
+
+static int __devinit pruss_probe(struct platform_device *dev)
+{
+ struct uio_info *p;
+ int ret = -ENODEV, cnt = 0, len;
+ struct resource *regs_prussio, *regs_l3ram, *regs_ddr;
+
+ info = kzalloc(sizeof(struct uio_info) * MAX_PRUSS_EVT, GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ /* Power on PRU in case its not done as part of boot-loader */
+ pruss_clk = clk_get(&dev->dev, "pruss");
+ if (IS_ERR(pruss_clk)) {
+ dev_err(&dev->dev, "Failed to get clock\n");
+ kfree(info);
+ ret = PTR_ERR(pruss_clk);
+ return ret;
+ } else {
+ clk_enable(pruss_clk);
+ }
+
+ regs_prussio = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!regs_prussio) {
+ dev_err(&dev->dev, "No PRUSS I/O resource specified\n");
+ goto out_free;
+ }
+
+ regs_l3ram = platform_get_resource(dev, IORESOURCE_MEM, 1);
+ if (!regs_l3ram) {
+ dev_err(&dev->dev, "No L3 RAM resource specified\n");
+ goto out_free;
+ }
+
+ regs_ddr = platform_get_resource(dev, IORESOURCE_MEM, 2);
+ if (!regs_ddr) {
+ dev_err(&dev->dev, "No External RAM resource specified\n");
+ goto out_free;
+ }
+
+ if (!regs_prussio->start || !regs_l3ram->start) {
+ dev_err(&dev->dev, "Invalid memory resource\n");
+ goto out_free;
+ }
+ len = resource_size(regs_ddr);
+ ddr_vaddr =
+ dma_alloc_coherent(&dev->dev, len, &ddr_paddr, GFP_KERNEL | GFP_DMA);
+ if (!ddr_vaddr) {
+ dev_err(&dev->dev, "Could not allocate external memory\n");
+ goto out_free;
+ }
+ len = resource_size(regs_prussio);
+ prussio_vaddr = ioremap(regs_prussio->start, len);
+ if (!prussio_vaddr) {
+ dev_err(&dev->dev, "Can't remap PRUSS I/O address range\n");
+ goto out_free;
+ }
+
+ for (cnt = 0, p = info; cnt < MAX_PRUSS_EVT; cnt++, p++) {
+ p->mem[0].internal_addr = prussio_vaddr;
+ p->mem[0].addr = regs_prussio->start;
+ p->mem[0].size = resource_size(regs_prussio);
+ p->mem[0].memtype = UIO_MEM_PHYS;
+
+ p->mem[1].addr = regs_l3ram->start;
+ p->mem[1].size = resource_size(regs_l3ram);
+ p->mem[1].memtype = UIO_MEM_PHYS;
+
+ p->mem[2].internal_addr = ddr_vaddr;
+ p->mem[2].addr = ddr_paddr;
+ p->mem[2].size = resource_size(regs_ddr);
+ p->mem[2].memtype = UIO_MEM_PHYS;
+
+ p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt);
+ p->version = "0.50";
+
+ /* Register PRUSS IRQ lines */
+ p->irq = IRQ_DA8XX_EVTOUT0 + cnt;
+ p->handler = pruss_handler;
+
+ ret = uio_register_device(&dev->dev, p);
+
+ if (ret < 0)
+ goto out_free;
+ }
+
+ platform_set_drvdata(dev, info);
+ return 0;
+
+out_free:
+ pruss_cleanup(dev, info);
+ return ret;
+}
+
+static int __devexit pruss_remove(struct platform_device *dev)
+{
+ struct uio_info *info = platform_get_drvdata(dev);
+
+ pruss_cleanup(dev, info);
+ platform_set_drvdata(dev, NULL);
+ return 0;
+}
+
+static struct platform_driver pruss_driver = {
+ .probe = pruss_probe,
+ .remove = __devexit_p(pruss_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pruss_init_module(void)
+{
+ return platform_driver_register(&pruss_driver);
+}
+
+module_init(pruss_init_module);
+
+static void __exit pruss_exit_module(void)
+{
+ platform_driver_unregister(&pruss_driver);
+}
+
+module_exit(pruss_exit_module);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Amit Chatterjee <amit.chatterjee@ti.com>");
+MODULE_AUTHOR("Pratheesh Gangadhar <pratheesh@ti.com>");
--
1.6.0.6
^ permalink raw reply related
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