* Re: [PATCH 9/14] PM / Blackfin: Use struct syscore_ops instead of sysdevs for PM
From: Rafael J. Wysocki @ 2011-04-18 21:43 UTC (permalink / raw)
To: Mike Frysinger
Cc: Kevin Hilman, Guan Xuetao, Russell King, Konrad Rzeszutek Wilk,
Greg KH, LKML, Ralf Baechle, Jeremy Fitzhardinge, Ben Dooks,
Jiri Kosina, Kay Sievers, Linux PM mailing list, linux-omap,
linuxppc-dev, Hans-Christian Egtvedt, linux-arm-kernel
In-Reply-To: <BANLkTi=BRXtsG0wK6SbK-6L-xzwMccR3eQ@mail.gmail.com>
On Monday, April 18, 2011, Mike Frysinger wrote:
> On Sun, Apr 17, 2011 at 17:11, Rafael J. Wysocki wrote:
> > Convert some Blackfin architecture's code to using struct syscore_ops
> > objects for power management instead of sysdev classes and sysdevs.
> >
> > This simplifies the code and reduces the kernel's memory footprint.
> > It also is necessary for removing sysdevs from the kernel entirely in
> > the future.
>
> looks straight forward enough ...
> Acked-by: Mike Frysinger <vapier@gentoo.org>
>
> > +static struct syscore_ops nmi_syscore_ops = {
> > .resume = nmi_wdt_resume,
> > .suspend = nmi_wdt_suspend,
> > };
>
> a bit sad this couldnt be made const
Well, that would trigger a compiler warning from register_syscore_ops().
However, I'm going to make that change change everywhere at once when all of
the conversions have been made, since it looks like we're only going to have
static syscore_ops.
Thanks,
Rafael
^ permalink raw reply
* Re: [PATCH 10/15] powerpc: Define slb0_limit() for BOOK3E
From: Benjamin Herrenschmidt @ 2011-04-18 21:41 UTC (permalink / raw)
To: Kumar Gala
Cc: Michael Ellerman, Jimi Xenidis, jack, imunsie, linuxppc-dev,
David Gibson
In-Reply-To: <DB59DA71-C6DA-4E65-9251-C29B973345AD@freescale.com>
On Mon, 2011-04-18 at 07:42 -0500, Kumar Gala wrote:
> Let's rename this function to something 'linear_map'. As on FSL
> Book-E 64 we do things a bit differently and have more covered in
> linear map than 1G
It's not quite linear_map. It's whatever can be accessed without taking
exceptions. IE. What is bolted.
It should probably go into a variable initialized by the mm code tho.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 12/15] powerpc/book3e: Use way 3 for linear mapping bolted entry
From: Benjamin Herrenschmidt @ 2011-04-18 21:40 UTC (permalink / raw)
To: Kumar Gala
Cc: Michael Ellerman, Jimi Xenidis, jack, imunsie, linuxppc-dev,
David Gibson
In-Reply-To: <FE1E8891-E134-4559-9F26-BAFC36B258AC@kernel.crashing.org>
On Mon, 2011-04-18 at 07:43 -0500, Kumar Gala wrote:
> On Apr 15, 2011, at 3:32 AM, Michael Ellerman wrote:
>
> > From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> >
> > An erratum on A2 can lead to the bolted entry we insert for the linear
> > mapping being evicted, to avoid that write the bolted entry to way 3.
> >
> > Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> > Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> > ---
> > arch/powerpc/kernel/exceptions-64e.S | 5 +++--
> > 1 files changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
> > index 5c43063..e6c0926 100644
> > --- a/arch/powerpc/kernel/exceptions-64e.S
> > +++ b/arch/powerpc/kernel/exceptions-64e.S
> > @@ -864,8 +864,9 @@ have_hes:
> > * that will have to be made dependent on whether we are running under
> > * a hypervisor I suppose.
> > */
> > - ori r3,r3,MAS0_HES | MAS0_WQ_ALLWAYS
> > - mtspr SPRN_MAS0,r3
> > + ori r11,r3,MAS0_WQ_ALLWAYS
> > + oris r11,r11,MAS0_ESEL(3)@h /* Use way 3: workaround A2 erratum 376 */
> > + mtspr SPRN_MAS0,r11
> > lis r3,(MAS1_VALID | MAS1_IPROT)@h
> > ori r3,r3,BOOK3E_PAGESZ_1GB << MAS1_TSIZE_SHIFT
> > mtspr SPRN_MAS1,r3
>
> Seems like this should have a MMU Feature bit or something for A2.
Too early. We haven't detected the CPU and are establishing the initial
TLB entry here.
Any reason why that wouldn't work on something else anyways ?
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 14/15] powerpc: Add WSP platform
From: Benjamin Herrenschmidt @ 2011-04-18 21:39 UTC (permalink / raw)
To: Kumar Gala
Cc: Michael Ellerman, Jimi Xenidis, jack, imunsie, linuxppc-dev,
David Gibson
In-Reply-To: <A6E5DD55-F9D1-430E-BAA7-E770523821A0@kernel.crashing.org>
On Mon, 2011-04-18 at 07:46 -0500, Kumar Gala wrote:
>
> Can this be moved into kernel/cpu_setup_a2.S. This and the debug
> patch that follows are bit ugly.
Well, the code per-se is not really A2 specific... the labels and
comments are :-)
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH V14 4/4] ptp: Added a clock driver for the National Semiconductor PHYTER.
From: Ben Hutchings @ 2011-04-18 20:57 UTC (permalink / raw)
To: Richard Cochran
Cc: Thomas Gleixner, Rodolfo Giometti, Arnd Bergmann, Peter Zijlstra,
linux-api, devicetree-discuss, linux-kernel, Russell King,
Paul Mackerras, John Stultz, Alan Cox, netdev, Mike Frysinger,
Christoph Lameter, linuxppc-dev, David Miller, linux-arm-kernel,
Krzysztof Halasa
In-Reply-To: <1728ffb5735c2a04876a69ad55427c4e7b5a1bd7.1303107532.git.richard.cochran@omicron.at>
On Mon, 2011-04-18 at 08:30 +0200, Richard Cochran wrote:
> This patch adds support for the PTP clock found on the DP83640.
> The basic clock operations and one external time stamp have
> been implemented.
[...]
> --- /dev/null
> +++ b/drivers/net/phy/dp83640.c
[...]
> +static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
> +{
> + u16 *seqid;
Should be __be16 *, and similarly for the casts.
> + u8 *msgtype, *data = skb_mac_header(skb);
> +
> + /* check sequenceID, messageType, 12 bit hash of offset 20-29 */
> + /* We assume that the IPv4 header has no options. */
Does the hardware definitely not timestamp received packets with IP
options?
> + switch (type) {
> + case PTP_CLASS_V1_IPV4:
> + msgtype = data + 42 + 32;
> + seqid = (u16 *)(data + 42 + 30);
> + break;
> + case PTP_CLASS_V1_IPV6:
> + msgtype = data + 62 + 32;
> + seqid = (u16 *)(data + 62 + 30);
> + break;
> + case PTP_CLASS_V2_IPV4:
> + msgtype = data + 42 + 0;
> + seqid = (u16 *)(data + 42 + 30);
> + break;
> + case PTP_CLASS_V2_IPV6:
> + msgtype = data + 62 + 0;
> + seqid = (u16 *)(data + 62 + 30);
> + break;
> + case PTP_CLASS_V2_L2:
> + msgtype = data + 14 + 0;
> + seqid = (u16 *)(data + 14 + 30);
> + break;
> + case PTP_CLASS_V2_VLAN:
> + msgtype = data + 18 + 0;
> + seqid = (u16 *)(data + 18 + 30);
> + break;
[...]
Would be better without the magic numbers.
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH V14 3/4] ptp: Added a clock driver for the IXP46x.
From: Ben Hutchings @ 2011-04-18 20:53 UTC (permalink / raw)
To: Richard Cochran
Cc: Thomas Gleixner, Rodolfo Giometti, Arnd Bergmann, Peter Zijlstra,
linux-api, devicetree-discuss, linux-kernel, Russell King,
Paul Mackerras, John Stultz, Alan Cox, netdev, Mike Frysinger,
Christoph Lameter, linuxppc-dev, David Miller, linux-arm-kernel,
Krzysztof Halasa
In-Reply-To: <dbee2487a57fd7f41e4efbbd2ddfb1313b8d71bc.1303107532.git.richard.cochran@omicron.at>
On Mon, 2011-04-18 at 08:29 +0200, Richard Cochran wrote:
> This patch adds a driver for the hardware time stamping unit found on the
> IXP465. The basic clock operations and an external trigger are implemented.
[...]
> --- a/drivers/net/arm/ixp4xx_eth.c
> +++ b/drivers/net/arm/ixp4xx_eth.c
[...]
> @@ -246,6 +255,169 @@ static int ports_open;
> static struct port *npe_port_tab[MAX_NPES];
> static struct dma_pool *dma_pool;
>
> +static struct sock_filter ptp_filter[] = {
> + PTP_FILTER
> +};
> +
> +static int ixp_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seq)
> +{
> + unsigned int type;
> + u16 *hi, *id;
> + u8 *lo, *data = skb->data;
> +
> + type = sk_run_filter(skb, ptp_filter);
> +
> + if (PTP_CLASS_V1_IPV4 == type) {
> +
> + id = (u16 *)(data + 42 + 30);
> + hi = (u16 *)(data + 42 + 22);
> + lo = data + 42 + 24;
[...]
PTP_FILTER does not verify that the packet length is sufficient to hold
a complete PTP header, nor does it require that the IPv4 header length
is 5 (i.e. 20 bytes). So you have to check those here rather than using
magic numbers.
I think you also need to use be16_to_cpup() to read 'id' and 'hi', since
the host byte order may vary.
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH 10/14] PM / MIPS: Use struct syscore_ops instead of sysdevs for PM
From: Rafael J. Wysocki @ 2011-04-18 20:03 UTC (permalink / raw)
To: Ralf Baechle
Cc: Kevin Hilman, Guan Xuetao, Russell King, Konrad Rzeszutek Wilk,
Greg KH, LKML, Jeremy Fitzhardinge, Ben Dooks, Jiri Kosina,
Kay Sievers, Mike Frysinger, Linux PM mailing list, linux-omap,
linuxppc-dev, Hans-Christian Egtvedt, linux-arm-kernel
In-Reply-To: <20110418101218.GA25325@linux-mips.org>
On Monday, April 18, 2011, Ralf Baechle wrote:
> This patch breaks the Alchemy kernel compile; below patch on top of it fixes
> that again.
>
> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Thanks! If you don't mind, I'd like to fold your patch into [10/14].
Rafael
> ---
> arch/mips/alchemy/common/irq.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> Index: linux-mips/arch/mips/alchemy/common/irq.c
> ===================================================================
> --- linux-mips.orig/arch/mips/alchemy/common/irq.c
> +++ linux-mips/arch/mips/alchemy/common/irq.c
> @@ -619,8 +619,8 @@ static struct syscore_ops alchemy_ic_sys
>
> static int __init alchemy_ic_syscore_init(void)
> {
> - alchemy_ic_data[0].base = ioremap(icbase[IC0_PHYS_ADDR], 0x1000);
> - alchemy_ic_data[1].base = ioremap(icbase[IC1_PHYS_ADDR], 0x1000);
> + alchemy_ic_data[0].base = ioremap(IC0_PHYS_ADDR, 0x1000);
> + alchemy_ic_data[1].base = ioremap(IC1_PHYS_ADDR, 0x1000);
>
> register_syscore_ops(&alchemy_ic_syscore_ops);
>
>
>
^ permalink raw reply
* Re: [PATCH 1/1] ppc64: fix build error when compiling with gcc-4.6.0
From: Stratos Psomadakis @ 2011-04-18 16:51 UTC (permalink / raw)
To: linux-kernel; +Cc: Stratos Psomadakis, linuxppc-dev
In-Reply-To: <1303144739-4407-2-git-send-email-psomas@cslab.ece.ntua.gr>
[-- Attachment #1: Type: text/plain, Size: 1102 bytes --]
On 18/04/2011 07:38 μμ, Stratos Psomadakis wrote:
> variable 'old' is set but not used, which results to a warning
> (-Werror=unused-but-set-variable) when compiling with gcc-4.6.0, and subsequent
> build failure.
> Remove the variable 'old', since it's not used anyway.
Something went wrong with git-send-email :/
So I send the first mail in the chain as a reply:
The build error was reported at the Gentoo Bugzilla [1].
When compiling with gcc-4.6.0, a build error occurs:
"variable ‘old’ set but not used [-Werror=unused-but-set-variable]
cc1: all warnings being treated as errors"
This patch removes the unnecessary assignments to the variable 'old', which cause
the compiler warning (used but not set), and build failure, and remove the variable completely.
I think it's ok to do that, since the variable is actually never used. Right?
(of course disabling CONFIG_PPC_WERROR would resolve the build failure, but cleaning up the code a bit, is better I think).
[1] https://bugs.gentoo.org/show_bug.cgi?id=363935
--
Stratos Psomadakis
<psomas@ece.ntua.gr>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
^ permalink raw reply
* Re: [PATCH 1/1] ppc64: fix build error when compiling with gcc-4.6.0
From: Stratos Psomadakis @ 2011-04-18 17:00 UTC (permalink / raw)
To: linux-kernel; +Cc: linuxppc-dev
In-Reply-To: <1303144739-4407-2-git-send-email-psomas@cslab.ece.ntua.gr>
Signed-off-by: Stratos Psomadakis <psomas@cslab.ece.ntua.gr>
--
Stratos Psomadakis
<psomas@ece.ntua.gr>
^ permalink raw reply
* [PATCH 1/1] ppc64: fix build error when compiling with gcc-4.6.0
From: Stratos Psomadakis @ 2011-04-18 16:38 UTC (permalink / raw)
To: linux-kernel; +Cc: Stratos Psomadakis, linuxppc-dev
In-Reply-To: <1303144739-4407-1-git-send-email-psomas@cslab.ece.ntua.gr>
variable 'old' is set but not used, which results to a warning
(-Werror=unused-but-set-variable) when compiling with gcc-4.6.0, and subsequent
build failure.
Remove the variable 'old', since it's not used anyway.
---
arch/powerpc/include/asm/pgtable-ppc64.h | 13 ++++++-------
1 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
index 2b09cd5..a49d592 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64.h
@@ -257,21 +257,20 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
{
- unsigned long old;
- if ((pte_val(*ptep) & _PAGE_RW) == 0)
- return;
- old = pte_update(mm, addr, ptep, _PAGE_RW, 0);
+ if ((pte_val(*ptep) & _PAGE_RW) == 0)
+ return;
+
+ pte_update(mm, addr, ptep, _PAGE_RW, 0);
}
static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
{
- unsigned long old;
-
if ((pte_val(*ptep) & _PAGE_RW) == 0)
return;
- old = pte_update(mm, addr, ptep, _PAGE_RW, 1);
+
+ pte_update(mm, addr, ptep, _PAGE_RW, 1);
}
/*
--
1.7.4.1
^ permalink raw reply related
* [PATCH 0/1] ppc64: fix build error when compiling with gcc-4.6.0
From: Stratos Psomadakis @ 2011-04-18 16:38 UTC (permalink / raw)
To: linux-kernel; +Cc: linuxppc-dev
The build error was reported at the Gentoo Bugzilla [1].
When compiling with gcc-4.6.0, a build error occurs:
"variable ‘old’ set but not used [-Werror=unused-but-set-variable]
cc1: all warnings being treated as errors"
This patch removes the unnecessary assignments to the variable, which cause
the compiler warning (used but not set), and build failure, and removes it
completely.
I think it's ok to do that, since the variable wasn't actually used anywhere
inside those two functions that caused the warning. Right?
[1] https://bugs.gentoo.org/show_bug.cgi?id=363935
^ permalink raw reply
* Re: [PATCH 14/15] powerpc: Add WSP platform
From: Kumar Gala @ 2011-04-18 12:46 UTC (permalink / raw)
To: Michael Ellerman; +Cc: Jimi Xenidis, linuxppc-dev, David Gibson, imunsie, jack
In-Reply-To: <02b9880aa9ef5d49b473c894bce886f2060f9f0b.1302856271.git.michael@ellerman.id.au>
On Apr 15, 2011, at 3:32 AM, Michael Ellerman wrote:
> diff --git a/arch/powerpc/kernel/exceptions-64e.S =
b/arch/powerpc/kernel/exceptions-64e.S
> index ab5c4dd..8e5d2c1 100644
> --- a/arch/powerpc/kernel/exceptions-64e.S
> +++ b/arch/powerpc/kernel/exceptions-64e.S
> @@ -864,6 +864,20 @@ have_hes:
> * that will have to be made dependent on whether we are running =
under
> * a hypervisor I suppose.
> */
> +
> + /* BEWARE, MAGIC
> + * This code is called as an ordinary function on the boot CPU. =
But to
> + * avoid duplication, this code is also used in SCOM bringup of
> + * secondary CPUs. We read the code between the =
initial_tlb_code_start
> + * and initial_tlb_code_end labels one instruction at a time and =
RAM it
> + * into the new core via SCOM. That doesn't process branches, so =
there
> + * must be none between those two labels. It also means if this =
code
> + * ever takes any parameters, the SCOM code must also be updated =
to
> + * provide them.
> + */
> + .globl a2_tlbinit_code_start
> +a2_tlbinit_code_start:
> +
> ori r11,r3,MAS0_WQ_ALLWAYS
> oris r11,r11,MAS0_ESEL(3)@h /* Use way 3: workaround A2 =
erratum 376 */
> mtspr SPRN_MAS0,r11
> @@ -880,6 +894,9 @@ have_hes:
> /* Write the TLB entry */
> tlbwe
>=20
> + .globl a2_tlbinit_after_linear_map
> +a2_tlbinit_after_linear_map:
> +
> /* Now we branch the new virtual address mapped by this entry */
> LOAD_REG_IMMEDIATE(r3,1f)
> mtctr r3
> @@ -931,10 +948,16 @@ have_hes:
> cmpw r3,r9
> blt 2b
>=20
> + .globl a2_tlbinit_after_iprot_flush
> +a2_tlbinit_after_iprot_flush:
> +
> PPC_TLBILX(0,0,0)
> sync
> isync
>=20
> + .globl a2_tlbinit_code_end
> +a2_tlbinit_code_end:
> +
> /* We translate LR and return */
> mflr r3
> tovirt(r3,r3)
Can this be moved into kernel/cpu_setup_a2.S. This and the debug patch =
that follows are bit ugly.
- k=
^ permalink raw reply
* Re: [PATCH 12/15] powerpc/book3e: Use way 3 for linear mapping bolted entry
From: Kumar Gala @ 2011-04-18 12:43 UTC (permalink / raw)
To: Michael Ellerman; +Cc: Jimi Xenidis, linuxppc-dev, David Gibson, imunsie, jack
In-Reply-To: <bbe411555c95e56ba427ebf638d5333b1870af77.1302856271.git.michael@ellerman.id.au>
On Apr 15, 2011, at 3:32 AM, Michael Ellerman wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>=20
> An erratum on A2 can lead to the bolted entry we insert for the linear
> mapping being evicted, to avoid that write the bolted entry to way 3.
>=20
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> ---
> arch/powerpc/kernel/exceptions-64e.S | 5 +++--
> 1 files changed, 3 insertions(+), 2 deletions(-)
>=20
> diff --git a/arch/powerpc/kernel/exceptions-64e.S =
b/arch/powerpc/kernel/exceptions-64e.S
> index 5c43063..e6c0926 100644
> --- a/arch/powerpc/kernel/exceptions-64e.S
> +++ b/arch/powerpc/kernel/exceptions-64e.S
> @@ -864,8 +864,9 @@ have_hes:
> * that will have to be made dependent on whether we are running =
under
> * a hypervisor I suppose.
> */
> - ori r3,r3,MAS0_HES | MAS0_WQ_ALLWAYS
> - mtspr SPRN_MAS0,r3
> + ori r11,r3,MAS0_WQ_ALLWAYS
> + oris r11,r11,MAS0_ESEL(3)@h /* Use way 3: workaround A2 =
erratum 376 */
> + mtspr SPRN_MAS0,r11
> lis r3,(MAS1_VALID | MAS1_IPROT)@h
> ori r3,r3,BOOK3E_PAGESZ_1GB << MAS1_TSIZE_SHIFT
> mtspr SPRN_MAS1,r3
Seems like this should have a MMU Feature bit or something for A2.
- k=
^ permalink raw reply
* Re: [PATCH 10/15] powerpc: Define slb0_limit() for BOOK3E
From: Kumar Gala @ 2011-04-18 12:42 UTC (permalink / raw)
To: Michael Ellerman; +Cc: Jimi Xenidis, linuxppc-dev, David Gibson, imunsie, jack
In-Reply-To: <021a5af117537ce9f7c6c3b27310f15851ab5034.1302856271.git.michael@ellerman.id.au>
On Apr 15, 2011, at 3:32 AM, Michael Ellerman wrote:
> From: Michael Ellerman <michael@ellerman.id.au>
>=20
> On BOOK3E we don't have an SLB 0, but the equivalent concept is the
> bolted entry mapping the kernel. Currently this is a 1G entry, so
> for now hardcode that. This will probably need to be reworked in
> future.
>=20
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> ---
> arch/powerpc/kernel/setup_64.c | 4 ++++
> 1 files changed, 4 insertions(+), 0 deletions(-)
>=20
> diff --git a/arch/powerpc/kernel/setup_64.c =
b/arch/powerpc/kernel/setup_64.c
> index 91a5cc5..3d0daf4 100644
> --- a/arch/powerpc/kernel/setup_64.c
> +++ b/arch/powerpc/kernel/setup_64.c
> @@ -436,10 +436,14 @@ void __init setup_system(void)
>=20
> static u64 slb0_limit(void)
> {
> +#ifdef CONFIG_PPC_BOOK3E
> + return 1 << 30;
> +#else
> if (cpu_has_feature(CPU_FTR_1T_SEGMENT)) {
> return 1UL << SID_SHIFT_1T;
> }
> return 1UL << SID_SHIFT;
> +#endif
> }
>=20
Let's rename this function to something 'linear_map'. As on FSL Book-E =
64 we do things a bit differently and have more covered in linear map =
than 1G
> static void __init irqstack_early_init(void)
> --=20
> 1.7.1
>=20
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH 07/15] powerpc: Move CPU_FTRS_BASE_BOOK3E into cputable.h & update FTR masks
From: Kumar Gala @ 2011-04-18 12:37 UTC (permalink / raw)
To: Michael Ellerman; +Cc: Jimi Xenidis, linuxppc-dev, David Gibson, imunsie, jack
In-Reply-To: <1a24282746fd056fb51dda3b25d160d2fc609da5.1302856271.git.michael@ellerman.id.au>
On Apr 15, 2011, at 3:32 AM, Michael Ellerman wrote:
> From: Michael Ellerman <michael@ellerman.id.au>
>
> Where they belong with all the others. Remove SMT which may not be
> true for all BOOK3E parts.
>
> Currently the FTRS_POSSIBLE & FTRS_ALWAYS are defined for 64 or 32 bit.
> Now that we have BOOK3E we need to split it three ways, BOOK3S, BOOK3E,
> and 32-bit.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> ---
> arch/powerpc/include/asm/cputable.h | 17 +++++++++++++----
> arch/powerpc/kernel/cputable.c | 3 ---
> 2 files changed, 13 insertions(+), 7 deletions(-)
will probably need some updating based on:
commit 11ed0db9f6c7811233632d2ab79c50c011b89902
Author: Kumar Gala <galak@kernel.crashing.org>
Date: Wed Apr 6 00:11:06 2011 -0500
powerpc/book3e: Fix CPU feature handling on 64-bit e5500
The CPU_FTRS_POSSIBLE and CPU_FTRS_ALWAYS defines did not encompass
e5500 CPU features when built for 64-bit. This causes issues with
cpu_has_feature() as it utilizes the POSSIBLE & ALWAYS defines as part
of its check.
Create a unique CPU_FTRS_E5500 (as its different from CPU_FTRS_E500MC),
created a new group for 64-bit Book3e based CPUs and add CPU_FTRS_E5500
to that group.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
- k
^ permalink raw reply
* Re: [PATCH 10/14] PM / MIPS: Use struct syscore_ops instead of sysdevs for PM
From: Ralf Baechle @ 2011-04-18 10:12 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Kevin Hilman, Guan Xuetao, Russell King, Konrad Rzeszutek Wilk,
Greg KH, LKML, Jeremy Fitzhardinge, Ben Dooks, Jiri Kosina,
Kay Sievers, Mike Frysinger, Linux PM mailing list, linux-omap,
linuxppc-dev, Hans-Christian Egtvedt, linux-arm-kernel
In-Reply-To: <201104172312.35060.rjw@sisk.pl>
This patch breaks the Alchemy kernel compile; below patch on top of it fixes
that again.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/alchemy/common/irq.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Index: linux-mips/arch/mips/alchemy/common/irq.c
===================================================================
--- linux-mips.orig/arch/mips/alchemy/common/irq.c
+++ linux-mips/arch/mips/alchemy/common/irq.c
@@ -619,8 +619,8 @@ static struct syscore_ops alchemy_ic_sys
static int __init alchemy_ic_syscore_init(void)
{
- alchemy_ic_data[0].base = ioremap(icbase[IC0_PHYS_ADDR], 0x1000);
- alchemy_ic_data[1].base = ioremap(icbase[IC1_PHYS_ADDR], 0x1000);
+ alchemy_ic_data[0].base = ioremap(IC0_PHYS_ADDR, 0x1000);
+ alchemy_ic_data[1].base = ioremap(IC1_PHYS_ADDR, 0x1000);
register_syscore_ops(&alchemy_ic_syscore_ops);
^ permalink raw reply
* Re: [PATCH 2/14] PM: Add missing syscore_suspend() and syscore_resume() calls
From: Ian Campbell @ 2011-04-18 8:51 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Kevin Hilman, Guan Xuetao, Russell King, Konrad Rzeszutek Wilk,
Greg KH, LKML, Ralf Baechle, Jeremy Fitzhardinge, Ben Dooks,
Jiri Kosina, Kay Sievers, Mike Frysinger, Linux PM mailing list,
linux-omap, linuxppc-dev, Hans-Christian Egtvedt,
linux-arm-kernel
In-Reply-To: <201104172306.49462.rjw@sisk.pl>
On Sun, 2011-04-17 at 23:06 +0200, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rjw@sisk.pl>
>
> Device suspend/resume infrastructure is used not only by the suspend
> and hibernate code in kernel/power, but also by , APM, Xen and the
> kexec jump feature. However, commit 40dc166cb5dddbd36aa4ad11c03915ea
> (PM / Core: Introduce struct syscore_ops for core subsystems PM)
> failed to add syscore_suspend() and syscore_resume() calls to that
> code, which generally leads to breakage when the features in question
> are used.
>
> To fix this problem, add the missing syscore_suspend() and
> syscore_resume() calls to arch/x86/kernel/apm_32.c, kernel/kexec.c
> and drivers/xen/manage.c.
Xen bit looks ok to me:
Acked-by: Ian Campbell <ian.campbell@citrix.com>
>
> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> ---
> arch/x86/kernel/apm_32.c | 5 +++++
> drivers/xen/manage.c | 9 ++++++++-
> kernel/kexec.c | 7 +++++++
> 3 files changed, 20 insertions(+), 1 deletion(-)
>
> Index: linux-2.6/kernel/kexec.c
> ===================================================================
> --- linux-2.6.orig/kernel/kexec.c
> +++ linux-2.6/kernel/kexec.c
> @@ -33,6 +33,7 @@
> #include <linux/vmalloc.h>
> #include <linux/swap.h>
> #include <linux/kmsg_dump.h>
> +#include <linux/syscore_ops.h>
>
> #include <asm/page.h>
> #include <asm/uaccess.h>
> @@ -1532,6 +1533,11 @@ int kernel_kexec(void)
> local_irq_disable();
> /* Suspend system devices */
> error = sysdev_suspend(PMSG_FREEZE);
> + if (!error) {
> + error = syscore_suspend();
> + if (error)
> + sysdev_resume();
> + }
> if (error)
> goto Enable_irqs;
> } else
> @@ -1546,6 +1552,7 @@ int kernel_kexec(void)
>
> #ifdef CONFIG_KEXEC_JUMP
> if (kexec_image->preserve_context) {
> + syscore_resume();
> sysdev_resume();
> Enable_irqs:
> local_irq_enable();
> Index: linux-2.6/drivers/xen/manage.c
> ===================================================================
> --- linux-2.6.orig/drivers/xen/manage.c
> +++ linux-2.6/drivers/xen/manage.c
> @@ -8,6 +8,7 @@
> #include <linux/sysrq.h>
> #include <linux/stop_machine.h>
> #include <linux/freezer.h>
> +#include <linux/syscore_ops.h>
>
> #include <xen/xen.h>
> #include <xen/xenbus.h>
> @@ -70,8 +71,13 @@ static int xen_suspend(void *data)
> BUG_ON(!irqs_disabled());
>
> err = sysdev_suspend(PMSG_FREEZE);
> + if (!err) {
> + err = syscore_suspend();
> + if (err)
> + sysdev_resume();
> + }
> if (err) {
> - printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
> + printk(KERN_ERR "xen_suspend: system core suspend failed: %d\n",
> err);
> return err;
> }
> @@ -95,6 +101,7 @@ static int xen_suspend(void *data)
> xen_timer_resume();
> }
>
> + syscore_resume();
> sysdev_resume();
>
> return 0;
> Index: linux-2.6/arch/x86/kernel/apm_32.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/apm_32.c
> +++ linux-2.6/arch/x86/kernel/apm_32.c
> @@ -228,6 +228,7 @@
> #include <linux/kthread.h>
> #include <linux/jiffies.h>
> #include <linux/acpi.h>
> +#include <linux/syscore_ops.h>
>
> #include <asm/system.h>
> #include <asm/uaccess.h>
> @@ -1238,6 +1239,7 @@ static int suspend(int vetoable)
>
> local_irq_disable();
> sysdev_suspend(PMSG_SUSPEND);
> + syscore_suspend();
>
> local_irq_enable();
>
> @@ -1255,6 +1257,7 @@ static int suspend(int vetoable)
> apm_error("suspend", err);
> err = (err == APM_SUCCESS) ? 0 : -EIO;
>
> + syscore_resume();
> sysdev_resume();
> local_irq_enable();
>
> @@ -1280,6 +1283,7 @@ static void standby(void)
>
> local_irq_disable();
> sysdev_suspend(PMSG_SUSPEND);
> + syscore_suspend();
> local_irq_enable();
>
> err = set_system_power_state(APM_STATE_STANDBY);
> @@ -1287,6 +1291,7 @@ static void standby(void)
> apm_error("standby", err);
>
> local_irq_disable();
> + syscore_resume();
> sysdev_resume();
> local_irq_enable();
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
--
Ian Campbell
Tact in audacity is knowing how far you can go without going too far.
-- Jean Cocteau
^ permalink raw reply
* Re: [PATCH V14 3/4] ptp: Added a clock driver for the IXP46x.
From: Arnd Bergmann @ 2011-04-18 8:26 UTC (permalink / raw)
To: Richard Cochran
Cc: Thomas Gleixner, Rodolfo Giometti, Peter Zijlstra, linux-api,
devicetree-discuss, linux-kernel, Russell King, Paul Mackerras,
John Stultz, Alan Cox, netdev, Mike Frysinger, Christoph Lameter,
linuxppc-dev, David Miller, linux-arm-kernel, Krzysztof Halasa
In-Reply-To: <201104181021.01279.arnd@arndb.de>
On Monday 18 April 2011, Arnd Bergmann wrote:
> On Monday 18 April 2011, Richard Cochran wrote:
> > On Mon, Apr 18, 2011 at 08:56:03AM +0200, Arnd Bergmann wrote:
> > > On Monday 18 April 2011, Richard Cochran wrote:
> > > > +
> > > > + lo = __raw_readl(®s->channel[ch].src_uuid_lo);
> > > > + hi = __raw_readl(®s->channel[ch].src_uuid_hi);
> > > > +
> > >
> > > I guess you should use readl(), not __raw_readl() here. The __raw_* functions
> > > are not meant for device drivers.
> >
> > Krzysztof had a different opinion about this.
> >
> > https://lkml.org/lkml/2011/1/8/67
> >
> > Anyway, it is his driver, and I just followed what he does elsewhere
> > in the driver. It make sense to me to keep the driver consistent.
> > Maybe we should make the change throughout?
>
> It would certainly be useful to fix it up. I now realized that this driver
> supports both big-endian and little-endian configurations, so just using
> readl() is certainly broken.
> There should probably be an ixp specific version of the safe I/O accessors
> to deal with it on all on-chip peripherals in a safe way.
Anyway, not your problem then, just leave it like it is.
Acked-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply
* Re: [PATCH V14 3/4] ptp: Added a clock driver for the IXP46x.
From: Arnd Bergmann @ 2011-04-18 8:21 UTC (permalink / raw)
To: Richard Cochran
Cc: Thomas Gleixner, Rodolfo Giometti, Peter Zijlstra, linux-api,
devicetree-discuss, linux-kernel, Russell King, Paul Mackerras,
John Stultz, Alan Cox, netdev, Mike Frysinger, Christoph Lameter,
linuxppc-dev, David Miller, linux-arm-kernel, Krzysztof Halasa
In-Reply-To: <20110418080606.GA3809@riccoc20.at.omicron.at>
On Monday 18 April 2011, Richard Cochran wrote:
> On Mon, Apr 18, 2011 at 08:56:03AM +0200, Arnd Bergmann wrote:
> > On Monday 18 April 2011, Richard Cochran wrote:
> > > +
> > > + lo = __raw_readl(®s->channel[ch].src_uuid_lo);
> > > + hi = __raw_readl(®s->channel[ch].src_uuid_hi);
> > > +
> >
> > I guess you should use readl(), not __raw_readl() here. The __raw_* functions
> > are not meant for device drivers.
>
> Krzysztof had a different opinion about this.
>
> https://lkml.org/lkml/2011/1/8/67
>
> Anyway, it is his driver, and I just followed what he does elsewhere
> in the driver. It make sense to me to keep the driver consistent.
> Maybe we should make the change throughout?
It would certainly be useful to fix it up. I now realized that this driver
supports both big-endian and little-endian configurations, so just using
readl() is certainly broken.
There should probably be an ixp specific version of the safe I/O accessors
to deal with it on all on-chip peripherals in a safe way.
Arnd
^ permalink raw reply
* Re: [PATCH V14 3/4] ptp: Added a clock driver for the IXP46x.
From: Richard Cochran @ 2011-04-18 8:16 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Thomas Gleixner, Rodolfo Giometti, Peter Zijlstra, linux-api,
devicetree-discuss, linux-kernel, Russell King, Paul Mackerras,
John Stultz, Alan Cox, netdev, Mike Frysinger, Christoph Lameter,
linuxppc-dev, David Miller, linux-arm-kernel, Krzysztof Halasa
In-Reply-To: <20110418080606.GA3809@riccoc20.at.omicron.at>
Also, I forgot to add Krzysztof's ack to the commit message, but he
did ack V12.
Thanks,
Richard
^ permalink raw reply
* Re: [PATCH V14 3/4] ptp: Added a clock driver for the IXP46x.
From: Richard Cochran @ 2011-04-18 8:06 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Thomas Gleixner, Rodolfo Giometti, Peter Zijlstra, linux-api,
devicetree-discuss, linux-kernel, Russell King, Paul Mackerras,
John Stultz, Alan Cox, netdev, Mike Frysinger, Christoph Lameter,
linuxppc-dev, David Miller, linux-arm-kernel, Krzysztof Halasa
In-Reply-To: <201104180856.04186.arnd@arndb.de>
On Mon, Apr 18, 2011 at 08:56:03AM +0200, Arnd Bergmann wrote:
> On Monday 18 April 2011, Richard Cochran wrote:
> > +
> > + lo = __raw_readl(®s->channel[ch].src_uuid_lo);
> > + hi = __raw_readl(®s->channel[ch].src_uuid_hi);
> > +
>
> I guess you should use readl(), not __raw_readl() here. The __raw_* functions
> are not meant for device drivers.
Krzysztof had a different opinion about this.
https://lkml.org/lkml/2011/1/8/67
Anyway, it is his driver, and I just followed what he does elsewhere
in the driver. It make sense to me to keep the driver consistent.
Maybe we should make the change throughout?
Thanks,
Richard
^ permalink raw reply
* Re: [PATCH V14 1/4] ptp: Added a brand new class driver for ptp clocks.
From: Arnd Bergmann @ 2011-04-18 6:54 UTC (permalink / raw)
To: Richard Cochran
Cc: Thomas Gleixner, Rodolfo Giometti, Peter Zijlstra, linux-api,
devicetree-discuss, linux-kernel, Russell King, Paul Mackerras,
John Stultz, Alan Cox, netdev, Mike Frysinger, Christoph Lameter,
linuxppc-dev, David Miller, linux-arm-kernel, Krzysztof Halasa
In-Reply-To: <7cabcc0bbd14733fa979fe08deccab8939204f24.1303107532.git.richard.cochran@omicron.at>
On Monday 18 April 2011, Richard Cochran wrote:
> This patch adds an infrastructure for hardware clocks that implement
> IEEE 1588, the Precision Time Protocol (PTP). A class driver offers a
> registration method to particular hardware clock drivers. Each clock is
> presented as a standard POSIX clock.
>
> The ancillary clock features are exposed in two different ways, via
> the sysfs and by a character device.
>
> Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
Acked-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply
* Re: [PATCH V14 3/4] ptp: Added a clock driver for the IXP46x.
From: Arnd Bergmann @ 2011-04-18 6:56 UTC (permalink / raw)
To: Richard Cochran
Cc: Thomas Gleixner, Rodolfo Giometti, Peter Zijlstra, linux-api,
devicetree-discuss, linux-kernel, Russell King, Paul Mackerras,
John Stultz, Alan Cox, netdev, Mike Frysinger, Christoph Lameter,
linuxppc-dev, David Miller, linux-arm-kernel, Krzysztof Halasa
In-Reply-To: <dbee2487a57fd7f41e4efbbd2ddfb1313b8d71bc.1303107532.git.richard.cochran@omicron.at>
On Monday 18 April 2011, Richard Cochran wrote:
> +static void ixp_rx_timestamp(struct port *port, struct sk_buff *skb)
> +{
> + struct skb_shared_hwtstamps *shhwtstamps;
> + struct ixp46x_ts_regs *regs;
> + u64 ns;
> + u32 ch, hi, lo, val;
> + u16 uid, seq;
> +
> + if (!port->hwts_rx_en)
> + return;
> +
> + ch = PORT2CHANNEL(port);
> +
> + regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
> +
> + val = __raw_readl(®s->channel[ch].ch_event);
> +
> + if (!(val & RX_SNAPSHOT_LOCKED))
> + return;
> +
> + lo = __raw_readl(®s->channel[ch].src_uuid_lo);
> + hi = __raw_readl(®s->channel[ch].src_uuid_hi);
> +
I guess you should use readl(), not __raw_readl() here. The __raw_* functions
are not meant for device drivers.
Arnd
^ permalink raw reply
* [git pull] Please pull powerpc.git merge branch
From: Benjamin Herrenschmidt @ 2011-04-18 6:35 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linuxppc-dev list, Andrew Morton, Linux Kernel list
Hi Linus !
Here are a few fixes and quirks for powerpc post -rc3. Hopefully that
should be the end of it pending major bugs/issues/regressions.
Cheers,
Ben.
The following changes since commit a1b49cb7e2a7961ec3aa8b64860bf480d4ec9077:
Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging (2011-04-17 17:37:02 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git merge
Anton Blanchard (1):
powerpc: Fix oops if scan_dispatch_log is called too early
Benjamin Herrenschmidt (2):
Merge remote branch 'kumar/merge' into merge
powerpc/powermac: Build fix with SMP and CPU hotplug
Eric B Munson (1):
powerpc/perf_event: Skip updating kernel counters if register value shrinks
Kumar Gala (2):
powerpc/book3e: Fix CPU feature handling on 64-bit e5500
powerpc/85xx: disable Suspend support if SMP enabled
Nishanth Aravamudan (1):
powerpc/pseries: Use a kmem cache for DTL buffers
Paul Gortmaker (1):
powerpc/kexec: Fix regression causing compile failure on UP
Prabhakar Kushwaha (2):
powerpc/85xx: Don't add disabled PCIe devices
powerpc: Check device status before adding serial device
Scott Wood (1):
powerpc/e500mc: Remove CPU_FTR_MAYBE_CAN_NAP/CPU_FTR_MAYBE_CAN_DOZE
Stefan Roese (1):
powerpc: Don't write protect kernel text with CONFIG_DYNAMIC_FTRACE enabled
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/cputable.h | 16 ++++++++++++-
arch/powerpc/include/asm/pte-common.h | 2 +-
arch/powerpc/kernel/cputable.c | 2 +-
arch/powerpc/kernel/crash.c | 12 +++++-----
arch/powerpc/kernel/legacy_serial.c | 8 ++++--
arch/powerpc/kernel/perf_event.c | 37 +++++++++++++++++++++++++------
arch/powerpc/kernel/time.c | 3 ++
arch/powerpc/platforms/powermac/smp.c | 8 ++++--
arch/powerpc/platforms/pseries/setup.c | 12 ++++++++-
arch/powerpc/sysdev/fsl_pci.c | 5 ++++
11 files changed, 81 insertions(+), 26 deletions(-)
^ permalink raw reply
* [PATCH V14 4/4] ptp: Added a clock driver for the National Semiconductor PHYTER.
From: Richard Cochran @ 2011-04-18 6:30 UTC (permalink / raw)
To: linux-kernel
Cc: Thomas Gleixner, Rodolfo Giometti, Arnd Bergmann, Peter Zijlstra,
linux-api, devicetree-discuss, Russell King, Paul Mackerras,
John Stultz, linux-arm-kernel, netdev, Mike Frysinger,
Christoph Lameter, linuxppc-dev, David Miller, Alan Cox,
Krzysztof Halasa
In-Reply-To: <cover.1303107532.git.richard.cochran@omicron.at>
This patch adds support for the PTP clock found on the DP83640.
The basic clock operations and one external time stamp have
been implemented.
Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
---
drivers/net/phy/Makefile | 1 +
drivers/net/phy/dp83640.c | 1100 +++++++++++++++++++++++++++++++++++++++++
drivers/net/phy/dp83640_reg.h | 267 ++++++++++
drivers/ptp/Kconfig | 19 +
4 files changed, 1387 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/phy/dp83640.c
create mode 100644 drivers/net/phy/dp83640_reg.h
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 13bebab..2333215 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_FIXED_PHY) += fixed.o
obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
obj-$(CONFIG_NATIONAL_PHY) += national.o
+obj-$(CONFIG_DP83640_PHY) += dp83640.o
obj-$(CONFIG_STE10XP) += ste10Xp.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
new file mode 100644
index 0000000..11c7e2d
--- /dev/null
+++ b/drivers/net/phy/dp83640.c
@@ -0,0 +1,1100 @@
+/*
+ * Driver for the National Semiconductor DP83640 PHYTER
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ * 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/ethtool.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/net_tstamp.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/ptp_classify.h>
+#include <linux/ptp_clock_kernel.h>
+
+#include "dp83640_reg.h"
+
+#define DP83640_PHY_ID 0x20005ce1
+#define PAGESEL 0x13
+#define LAYER4 0x02
+#define LAYER2 0x01
+#define MAX_RXTS 4
+#define MAX_TXTS 4
+#define N_EXT_TS 1
+#define PSF_PTPVER 2
+#define PSF_EVNT 0x4000
+#define PSF_RX 0x2000
+#define PSF_TX 0x1000
+#define EXT_EVENT 1
+#define EXT_GPIO 1
+#define CAL_EVENT 2
+#define CAL_GPIO 9
+#define CAL_TRIGGER 2
+
+/* phyter seems to miss the mark by 16 ns */
+#define ADJTIME_FIX 16
+
+#if defined(__BIG_ENDIAN)
+#define ENDIAN_FLAG 0
+#elif defined(__LITTLE_ENDIAN)
+#define ENDIAN_FLAG PSF_ENDIAN
+#endif
+
+#define SKB_PTP_TYPE(__skb) (*(unsigned int *)((__skb)->cb))
+
+struct phy_rxts {
+ u16 ns_lo; /* ns[15:0] */
+ u16 ns_hi; /* overflow[1:0], ns[29:16] */
+ u16 sec_lo; /* sec[15:0] */
+ u16 sec_hi; /* sec[31:16] */
+ u16 seqid; /* sequenceId[15:0] */
+ u16 msgtype; /* messageType[3:0], hash[11:0] */
+};
+
+struct phy_txts {
+ u16 ns_lo; /* ns[15:0] */
+ u16 ns_hi; /* overflow[1:0], ns[29:16] */
+ u16 sec_lo; /* sec[15:0] */
+ u16 sec_hi; /* sec[31:16] */
+};
+
+struct rxts {
+ struct list_head list;
+ unsigned long tmo;
+ u64 ns;
+ u16 seqid;
+ u8 msgtype;
+ u16 hash;
+};
+
+struct dp83640_clock;
+
+struct dp83640_private {
+ struct list_head list;
+ struct dp83640_clock *clock;
+ struct phy_device *phydev;
+ struct work_struct ts_work;
+ int hwts_tx_en;
+ int hwts_rx_en;
+ int layer;
+ int version;
+ /* remember state of cfg0 during calibration */
+ int cfg0;
+ /* remember the last event time stamp */
+ struct phy_txts edata;
+ /* list of rx timestamps */
+ struct list_head rxts;
+ struct list_head rxpool;
+ struct rxts rx_pool_data[MAX_RXTS];
+ /* protects above three fields from concurrent access */
+ spinlock_t rx_lock;
+ /* queues of incoming and outgoing packets */
+ struct sk_buff_head rx_queue;
+ struct sk_buff_head tx_queue;
+};
+
+struct dp83640_clock {
+ /* keeps the instance in the 'phyter_clocks' list */
+ struct list_head list;
+ /* we create one clock instance per MII bus */
+ struct mii_bus *bus;
+ /* protects extended registers from concurrent access */
+ struct mutex extreg_lock;
+ /* remembers which page was last selected */
+ int page;
+ /* our advertised capabilities */
+ struct ptp_clock_info caps;
+ /* protects the three fields below from concurrent access */
+ struct mutex clock_lock;
+ /* the one phyter from which we shall read */
+ struct dp83640_private *chosen;
+ /* list of the other attached phyters, not chosen */
+ struct list_head phylist;
+ /* reference to our PTP hardware clock */
+ struct ptp_clock *ptp_clock;
+};
+
+/* globals */
+
+static int chosen_phy = -1;
+static ushort cal_gpio = 4;
+
+module_param(chosen_phy, int, 0444);
+module_param(cal_gpio, ushort, 0444);
+
+MODULE_PARM_DESC(chosen_phy, \
+ "The address of the PHY to use for the ancillary clock features");
+MODULE_PARM_DESC(cal_gpio, \
+ "Which GPIO line to use for synchronizing multiple PHYs");
+
+/* a list of clocks and a mutex to protect it */
+static LIST_HEAD(phyter_clocks);
+static DEFINE_MUTEX(phyter_clocks_lock);
+
+static void rx_timestamp_work(struct work_struct *work);
+
+/* extended register access functions */
+
+#define BROADCAST_ADDR 31
+
+static inline int broadcast_write(struct mii_bus *bus, u32 regnum, u16 val)
+{
+ return mdiobus_write(bus, BROADCAST_ADDR, regnum, val);
+}
+
+/* Caller must hold extreg_lock. */
+static int ext_read(struct phy_device *phydev, int page, u32 regnum)
+{
+ struct dp83640_private *dp83640 = phydev->priv;
+ int val;
+
+ if (dp83640->clock->page != page) {
+ broadcast_write(phydev->bus, PAGESEL, page);
+ dp83640->clock->page = page;
+ }
+ val = phy_read(phydev, regnum);
+
+ return val;
+}
+
+/* Caller must hold extreg_lock. */
+static void ext_write(int broadcast, struct phy_device *phydev,
+ int page, u32 regnum, u16 val)
+{
+ struct dp83640_private *dp83640 = phydev->priv;
+
+ if (dp83640->clock->page != page) {
+ broadcast_write(phydev->bus, PAGESEL, page);
+ dp83640->clock->page = page;
+ }
+ if (broadcast)
+ broadcast_write(phydev->bus, regnum, val);
+ else
+ phy_write(phydev, regnum, val);
+}
+
+/* Caller must hold extreg_lock. */
+static int tdr_write(int bc, struct phy_device *dev,
+ const struct timespec *ts, u16 cmd)
+{
+ ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_nsec & 0xffff);/* ns[15:0] */
+ ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_nsec >> 16); /* ns[31:16] */
+ ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_sec & 0xffff); /* sec[15:0] */
+ ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_sec >> 16); /* sec[31:16]*/
+
+ ext_write(bc, dev, PAGE4, PTP_CTL, cmd);
+
+ return 0;
+}
+
+/* convert phy timestamps into driver timestamps */
+
+static void phy2rxts(struct phy_rxts *p, struct rxts *rxts)
+{
+ u32 sec;
+
+ sec = p->sec_lo;
+ sec |= p->sec_hi << 16;
+
+ rxts->ns = p->ns_lo;
+ rxts->ns |= (p->ns_hi & 0x3fff) << 16;
+ rxts->ns += ((u64)sec) * 1000000000ULL;
+ rxts->seqid = p->seqid;
+ rxts->msgtype = (p->msgtype >> 12) & 0xf;
+ rxts->hash = p->msgtype & 0x0fff;
+ rxts->tmo = jiffies + HZ;
+}
+
+static u64 phy2txts(struct phy_txts *p)
+{
+ u64 ns;
+ u32 sec;
+
+ sec = p->sec_lo;
+ sec |= p->sec_hi << 16;
+
+ ns = p->ns_lo;
+ ns |= (p->ns_hi & 0x3fff) << 16;
+ ns += ((u64)sec) * 1000000000ULL;
+
+ return ns;
+}
+
+/* ptp clock methods */
+
+static int ptp_dp83640_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+ struct dp83640_clock *clock =
+ container_of(ptp, struct dp83640_clock, caps);
+ struct phy_device *phydev = clock->chosen->phydev;
+ u64 rate;
+ int neg_adj = 0;
+ u16 hi, lo;
+
+ if (ppb < 0) {
+ neg_adj = 1;
+ ppb = -ppb;
+ }
+ rate = ppb;
+ rate <<= 26;
+ rate = div_u64(rate, 1953125);
+
+ hi = (rate >> 16) & PTP_RATE_HI_MASK;
+ if (neg_adj)
+ hi |= PTP_RATE_DIR;
+
+ lo = rate & 0xffff;
+
+ mutex_lock(&clock->extreg_lock);
+
+ ext_write(1, phydev, PAGE4, PTP_RATEH, hi);
+ ext_write(1, phydev, PAGE4, PTP_RATEL, lo);
+
+ mutex_unlock(&clock->extreg_lock);
+
+ return 0;
+}
+
+static int ptp_dp83640_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ struct dp83640_clock *clock =
+ container_of(ptp, struct dp83640_clock, caps);
+ struct phy_device *phydev = clock->chosen->phydev;
+ struct timespec ts;
+ int err;
+
+ delta += ADJTIME_FIX;
+
+ ts = ns_to_timespec(delta);
+
+ mutex_lock(&clock->extreg_lock);
+
+ err = tdr_write(1, phydev, &ts, PTP_STEP_CLK);
+
+ mutex_unlock(&clock->extreg_lock);
+
+ return err;
+}
+
+static int ptp_dp83640_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+ struct dp83640_clock *clock =
+ container_of(ptp, struct dp83640_clock, caps);
+ struct phy_device *phydev = clock->chosen->phydev;
+ unsigned int val[4];
+
+ mutex_lock(&clock->extreg_lock);
+
+ ext_write(0, phydev, PAGE4, PTP_CTL, PTP_RD_CLK);
+
+ val[0] = ext_read(phydev, PAGE4, PTP_TDR); /* ns[15:0] */
+ val[1] = ext_read(phydev, PAGE4, PTP_TDR); /* ns[31:16] */
+ val[2] = ext_read(phydev, PAGE4, PTP_TDR); /* sec[15:0] */
+ val[3] = ext_read(phydev, PAGE4, PTP_TDR); /* sec[31:16] */
+
+ mutex_unlock(&clock->extreg_lock);
+
+ ts->tv_nsec = val[0] | (val[1] << 16);
+ ts->tv_sec = val[2] | (val[3] << 16);
+
+ return 0;
+}
+
+static int ptp_dp83640_settime(struct ptp_clock_info *ptp,
+ const struct timespec *ts)
+{
+ struct dp83640_clock *clock =
+ container_of(ptp, struct dp83640_clock, caps);
+ struct phy_device *phydev = clock->chosen->phydev;
+ int err;
+
+ mutex_lock(&clock->extreg_lock);
+
+ err = tdr_write(1, phydev, ts, PTP_LOAD_CLK);
+
+ mutex_unlock(&clock->extreg_lock);
+
+ return err;
+}
+
+static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ struct dp83640_clock *clock =
+ container_of(ptp, struct dp83640_clock, caps);
+ struct phy_device *phydev = clock->chosen->phydev;
+ u16 evnt;
+
+ switch (rq->type) {
+ case PTP_CLK_REQ_EXTTS:
+ if (rq->extts.index != 0)
+ return -EINVAL;
+ evnt = EVNT_WR | (EXT_EVENT & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
+ if (on) {
+ evnt |= (EXT_GPIO & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
+ evnt |= EVNT_RISE;
+ }
+ ext_write(0, phydev, PAGE5, PTP_EVNT, evnt);
+ return 0;
+ default:
+ break;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static u8 status_frame_dst[6] = { 0x01, 0x1B, 0x19, 0x00, 0x00, 0x00 };
+static u8 status_frame_src[6] = { 0x08, 0x00, 0x17, 0x0B, 0x6B, 0x0F };
+
+static void enable_status_frames(struct phy_device *phydev, bool on)
+{
+ u16 cfg0 = 0, ver;
+
+ if (on)
+ cfg0 = PSF_EVNT_EN | PSF_RXTS_EN | PSF_TXTS_EN | ENDIAN_FLAG;
+
+ ver = (PSF_PTPVER & VERSIONPTP_MASK) << VERSIONPTP_SHIFT;
+
+ ext_write(0, phydev, PAGE5, PSF_CFG0, cfg0);
+ ext_write(0, phydev, PAGE6, PSF_CFG1, ver);
+
+ if (!phydev->attached_dev) {
+ pr_warning("dp83640: expected to find an attached netdevice\n");
+ return;
+ }
+
+ if (on) {
+ if (dev_mc_add(phydev->attached_dev, status_frame_dst))
+ pr_warning("dp83640: failed to add mc address\n");
+ } else {
+ if (dev_mc_del(phydev->attached_dev, status_frame_dst))
+ pr_warning("dp83640: failed to delete mc address\n");
+ }
+}
+
+static bool is_status_frame(struct sk_buff *skb, int type)
+{
+ struct ethhdr *h = eth_hdr(skb);
+
+ if (PTP_CLASS_V2_L2 == type &&
+ !memcmp(h->h_source, status_frame_src, sizeof(status_frame_src)))
+ return true;
+ else
+ return false;
+}
+
+static int expired(struct rxts *rxts)
+{
+ return time_after(jiffies, rxts->tmo);
+}
+
+/* Caller must hold rx_lock. */
+static void prune_rx_ts(struct dp83640_private *dp83640)
+{
+ struct list_head *this, *next;
+ struct rxts *rxts;
+
+ list_for_each_safe(this, next, &dp83640->rxts) {
+ rxts = list_entry(this, struct rxts, list);
+ if (expired(rxts)) {
+ list_del_init(&rxts->list);
+ list_add(&rxts->list, &dp83640->rxpool);
+ }
+ }
+}
+
+/* synchronize the phyters so they act as one clock */
+
+static void enable_broadcast(struct phy_device *phydev, int init_page, int on)
+{
+ int val;
+ phy_write(phydev, PAGESEL, 0);
+ val = phy_read(phydev, PHYCR2);
+ if (on)
+ val |= BC_WRITE;
+ else
+ val &= ~BC_WRITE;
+ phy_write(phydev, PHYCR2, val);
+ phy_write(phydev, PAGESEL, init_page);
+}
+
+static void recalibrate(struct dp83640_clock *clock)
+{
+ s64 now, diff;
+ struct phy_txts event_ts;
+ struct timespec ts;
+ struct list_head *this;
+ struct dp83640_private *tmp;
+ struct phy_device *master = clock->chosen->phydev;
+ u16 cfg0, evnt, ptp_trig, trigger, val;
+
+ trigger = CAL_TRIGGER;
+
+ mutex_lock(&clock->extreg_lock);
+
+ /*
+ * enable broadcast, disable status frames, enable ptp clock
+ */
+ list_for_each(this, &clock->phylist) {
+ tmp = list_entry(this, struct dp83640_private, list);
+ enable_broadcast(tmp->phydev, clock->page, 1);
+ tmp->cfg0 = ext_read(tmp->phydev, PAGE5, PSF_CFG0);
+ ext_write(0, tmp->phydev, PAGE5, PSF_CFG0, 0);
+ ext_write(0, tmp->phydev, PAGE4, PTP_CTL, PTP_ENABLE);
+ }
+ enable_broadcast(master, clock->page, 1);
+ cfg0 = ext_read(master, PAGE5, PSF_CFG0);
+ ext_write(0, master, PAGE5, PSF_CFG0, 0);
+ ext_write(0, master, PAGE4, PTP_CTL, PTP_ENABLE);
+
+ /*
+ * enable an event timestamp
+ */
+ evnt = EVNT_WR | EVNT_RISE | EVNT_SINGLE;
+ evnt |= (CAL_EVENT & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
+ evnt |= (cal_gpio & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
+
+ list_for_each(this, &clock->phylist) {
+ tmp = list_entry(this, struct dp83640_private, list);
+ ext_write(0, tmp->phydev, PAGE5, PTP_EVNT, evnt);
+ }
+ ext_write(0, master, PAGE5, PTP_EVNT, evnt);
+
+ /*
+ * configure a trigger
+ */
+ ptp_trig = TRIG_WR | TRIG_IF_LATE | TRIG_PULSE;
+ ptp_trig |= (trigger & TRIG_CSEL_MASK) << TRIG_CSEL_SHIFT;
+ ptp_trig |= (cal_gpio & TRIG_GPIO_MASK) << TRIG_GPIO_SHIFT;
+ ext_write(0, master, PAGE5, PTP_TRIG, ptp_trig);
+
+ /* load trigger */
+ val = (trigger & TRIG_SEL_MASK) << TRIG_SEL_SHIFT;
+ val |= TRIG_LOAD;
+ ext_write(0, master, PAGE4, PTP_CTL, val);
+
+ /* enable trigger */
+ val &= ~TRIG_LOAD;
+ val |= TRIG_EN;
+ ext_write(0, master, PAGE4, PTP_CTL, val);
+
+ /* disable trigger */
+ val = (trigger & TRIG_SEL_MASK) << TRIG_SEL_SHIFT;
+ val |= TRIG_DIS;
+ ext_write(0, master, PAGE4, PTP_CTL, val);
+
+ /*
+ * read out and correct offsets
+ */
+ val = ext_read(master, PAGE4, PTP_STS);
+ pr_info("master PTP_STS 0x%04hx", val);
+ val = ext_read(master, PAGE4, PTP_ESTS);
+ pr_info("master PTP_ESTS 0x%04hx", val);
+ event_ts.ns_lo = ext_read(master, PAGE4, PTP_EDATA);
+ event_ts.ns_hi = ext_read(master, PAGE4, PTP_EDATA);
+ event_ts.sec_lo = ext_read(master, PAGE4, PTP_EDATA);
+ event_ts.sec_hi = ext_read(master, PAGE4, PTP_EDATA);
+ now = phy2txts(&event_ts);
+
+ list_for_each(this, &clock->phylist) {
+ tmp = list_entry(this, struct dp83640_private, list);
+ val = ext_read(tmp->phydev, PAGE4, PTP_STS);
+ pr_info("slave PTP_STS 0x%04hx", val);
+ val = ext_read(tmp->phydev, PAGE4, PTP_ESTS);
+ pr_info("slave PTP_ESTS 0x%04hx", val);
+ event_ts.ns_lo = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
+ event_ts.ns_hi = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
+ event_ts.sec_lo = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
+ event_ts.sec_hi = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
+ diff = now - (s64) phy2txts(&event_ts);
+ pr_info("slave offset %lld nanoseconds\n", diff);
+ diff += ADJTIME_FIX;
+ ts = ns_to_timespec(diff);
+ tdr_write(0, tmp->phydev, &ts, PTP_STEP_CLK);
+ }
+
+ /*
+ * restore status frames
+ */
+ list_for_each(this, &clock->phylist) {
+ tmp = list_entry(this, struct dp83640_private, list);
+ ext_write(0, tmp->phydev, PAGE5, PSF_CFG0, tmp->cfg0);
+ }
+ ext_write(0, master, PAGE5, PSF_CFG0, cfg0);
+
+ mutex_unlock(&clock->extreg_lock);
+}
+
+/* time stamping methods */
+
+static void decode_evnt(struct dp83640_private *dp83640,
+ struct phy_txts *phy_txts, u16 ests)
+{
+ struct ptp_clock_event event;
+ int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK;
+
+ switch (words) { /* fall through in every case */
+ case 3:
+ dp83640->edata.sec_hi = phy_txts->sec_hi;
+ case 2:
+ dp83640->edata.sec_lo = phy_txts->sec_lo;
+ case 1:
+ dp83640->edata.ns_hi = phy_txts->ns_hi;
+ case 0:
+ dp83640->edata.ns_lo = phy_txts->ns_lo;
+ }
+
+ event.type = PTP_CLOCK_EXTTS;
+ event.index = 0;
+ event.timestamp = phy2txts(&dp83640->edata);
+
+ ptp_clock_event(dp83640->clock->ptp_clock, &event);
+}
+
+static void decode_rxts(struct dp83640_private *dp83640,
+ struct phy_rxts *phy_rxts)
+{
+ struct rxts *rxts;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dp83640->rx_lock, flags);
+
+ prune_rx_ts(dp83640);
+
+ if (list_empty(&dp83640->rxpool)) {
+ pr_warning("dp83640: rx timestamp pool is empty\n");
+ goto out;
+ }
+ rxts = list_first_entry(&dp83640->rxpool, struct rxts, list);
+ list_del_init(&rxts->list);
+ phy2rxts(phy_rxts, rxts);
+ list_add_tail(&rxts->list, &dp83640->rxts);
+out:
+ spin_unlock_irqrestore(&dp83640->rx_lock, flags);
+}
+
+static void decode_txts(struct dp83640_private *dp83640,
+ struct phy_txts *phy_txts)
+{
+ struct skb_shared_hwtstamps shhwtstamps;
+ struct sk_buff *skb;
+ u64 ns;
+
+ /* We must already have the skb that triggered this. */
+
+ skb = skb_dequeue(&dp83640->tx_queue);
+
+ if (!skb) {
+ pr_warning("dp83640: have timestamp but tx_queue empty\n");
+ return;
+ }
+ ns = phy2txts(phy_txts);
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ shhwtstamps.hwtstamp = ns_to_ktime(ns);
+ skb_complete_tx_timestamp(skb, &shhwtstamps);
+}
+
+static void decode_status_frame(struct dp83640_private *dp83640,
+ struct sk_buff *skb)
+{
+ struct phy_rxts *phy_rxts;
+ struct phy_txts *phy_txts;
+ u8 *ptr;
+ int len, size;
+ u16 ests, type;
+
+ ptr = skb->data + 2;
+
+ for (len = skb_headlen(skb) - 2; len > sizeof(type); len -= size) {
+
+ type = *(u16 *)ptr;
+ ests = type & 0x0fff;
+ type = type & 0xf000;
+ len -= sizeof(type);
+ ptr += sizeof(type);
+
+ if (PSF_RX == type && len >= sizeof(*phy_rxts)) {
+
+ phy_rxts = (struct phy_rxts *) ptr;
+ decode_rxts(dp83640, phy_rxts);
+ size = sizeof(*phy_rxts);
+
+ } else if (PSF_TX == type && len >= sizeof(*phy_txts)) {
+
+ phy_txts = (struct phy_txts *) ptr;
+ decode_txts(dp83640, phy_txts);
+ size = sizeof(*phy_txts);
+
+ } else if (PSF_EVNT == type && len >= sizeof(*phy_txts)) {
+
+ phy_txts = (struct phy_txts *) ptr;
+ decode_evnt(dp83640, phy_txts, ests);
+ size = sizeof(*phy_txts);
+
+ } else {
+ size = 0;
+ break;
+ }
+ ptr += size;
+ }
+}
+
+static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
+{
+ u16 *seqid;
+ u8 *msgtype, *data = skb_mac_header(skb);
+
+ /* check sequenceID, messageType, 12 bit hash of offset 20-29 */
+ /* We assume that the IPv4 header has no options. */
+
+ switch (type) {
+ case PTP_CLASS_V1_IPV4:
+ msgtype = data + 42 + 32;
+ seqid = (u16 *)(data + 42 + 30);
+ break;
+ case PTP_CLASS_V1_IPV6:
+ msgtype = data + 62 + 32;
+ seqid = (u16 *)(data + 62 + 30);
+ break;
+ case PTP_CLASS_V2_IPV4:
+ msgtype = data + 42 + 0;
+ seqid = (u16 *)(data + 42 + 30);
+ break;
+ case PTP_CLASS_V2_IPV6:
+ msgtype = data + 62 + 0;
+ seqid = (u16 *)(data + 62 + 30);
+ break;
+ case PTP_CLASS_V2_L2:
+ msgtype = data + 14 + 0;
+ seqid = (u16 *)(data + 14 + 30);
+ break;
+ case PTP_CLASS_V2_VLAN:
+ msgtype = data + 18 + 0;
+ seqid = (u16 *)(data + 18 + 30);
+ break;
+ default:
+ return 0;
+ }
+
+ return (rxts->msgtype == (*msgtype & 0xf) &&
+ rxts->seqid == ntohs(*seqid));
+}
+
+static void dp83640_free_clocks(void)
+{
+ struct dp83640_clock *clock;
+ struct list_head *this, *next;
+
+ mutex_lock(&phyter_clocks_lock);
+
+ list_for_each_safe(this, next, &phyter_clocks) {
+ clock = list_entry(this, struct dp83640_clock, list);
+ if (!list_empty(&clock->phylist)) {
+ pr_warning("phy list non-empty while unloading");
+ BUG();
+ }
+ list_del(&clock->list);
+ mutex_destroy(&clock->extreg_lock);
+ mutex_destroy(&clock->clock_lock);
+ put_device(&clock->bus->dev);
+ kfree(clock);
+ }
+
+ mutex_unlock(&phyter_clocks_lock);
+}
+
+static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus)
+{
+ INIT_LIST_HEAD(&clock->list);
+ clock->bus = bus;
+ mutex_init(&clock->extreg_lock);
+ mutex_init(&clock->clock_lock);
+ INIT_LIST_HEAD(&clock->phylist);
+ clock->caps.owner = THIS_MODULE;
+ sprintf(clock->caps.name, "dp83640 timer");
+ clock->caps.max_adj = 1953124;
+ clock->caps.n_alarm = 0;
+ clock->caps.n_ext_ts = N_EXT_TS;
+ clock->caps.n_per_out = 0;
+ clock->caps.pps = 0;
+ clock->caps.adjfreq = ptp_dp83640_adjfreq;
+ clock->caps.adjtime = ptp_dp83640_adjtime;
+ clock->caps.gettime = ptp_dp83640_gettime;
+ clock->caps.settime = ptp_dp83640_settime;
+ clock->caps.enable = ptp_dp83640_enable;
+ /*
+ * Get a reference to this bus instance.
+ */
+ get_device(&bus->dev);
+}
+
+static int choose_this_phy(struct dp83640_clock *clock,
+ struct phy_device *phydev)
+{
+ if (chosen_phy == -1 && !clock->chosen)
+ return 1;
+
+ if (chosen_phy == phydev->addr)
+ return 1;
+
+ return 0;
+}
+
+static struct dp83640_clock *dp83640_clock_get(struct dp83640_clock *clock)
+{
+ if (clock)
+ mutex_lock(&clock->clock_lock);
+ return clock;
+}
+
+/*
+ * Look up and lock a clock by bus instance.
+ * If there is no clock for this bus, then create it first.
+ */
+static struct dp83640_clock *dp83640_clock_get_bus(struct mii_bus *bus)
+{
+ struct dp83640_clock *clock = NULL, *tmp;
+ struct list_head *this;
+
+ mutex_lock(&phyter_clocks_lock);
+
+ list_for_each(this, &phyter_clocks) {
+ tmp = list_entry(this, struct dp83640_clock, list);
+ if (tmp->bus == bus) {
+ clock = tmp;
+ break;
+ }
+ }
+ if (clock)
+ goto out;
+
+ clock = kzalloc(sizeof(struct dp83640_clock), GFP_KERNEL);
+ if (!clock)
+ goto out;
+
+ dp83640_clock_init(clock, bus);
+ list_add_tail(&phyter_clocks, &clock->list);
+out:
+ mutex_unlock(&phyter_clocks_lock);
+
+ return dp83640_clock_get(clock);
+}
+
+static void dp83640_clock_put(struct dp83640_clock *clock)
+{
+ mutex_unlock(&clock->clock_lock);
+}
+
+static int dp83640_probe(struct phy_device *phydev)
+{
+ struct dp83640_clock *clock;
+ struct dp83640_private *dp83640;
+ int err = -ENOMEM, i;
+
+ if (phydev->addr == BROADCAST_ADDR)
+ return 0;
+
+ clock = dp83640_clock_get_bus(phydev->bus);
+ if (!clock)
+ goto no_clock;
+
+ dp83640 = kzalloc(sizeof(struct dp83640_private), GFP_KERNEL);
+ if (!dp83640)
+ goto no_memory;
+
+ dp83640->phydev = phydev;
+ INIT_WORK(&dp83640->ts_work, rx_timestamp_work);
+
+ INIT_LIST_HEAD(&dp83640->rxts);
+ INIT_LIST_HEAD(&dp83640->rxpool);
+ for (i = 0; i < MAX_RXTS; i++)
+ list_add(&dp83640->rx_pool_data[i].list, &dp83640->rxpool);
+
+ phydev->priv = dp83640;
+
+ spin_lock_init(&dp83640->rx_lock);
+ skb_queue_head_init(&dp83640->rx_queue);
+ skb_queue_head_init(&dp83640->tx_queue);
+
+ dp83640->clock = clock;
+
+ if (choose_this_phy(clock, phydev)) {
+ clock->chosen = dp83640;
+ clock->ptp_clock = ptp_clock_register(&clock->caps);
+ if (IS_ERR(clock->ptp_clock)) {
+ err = PTR_ERR(clock->ptp_clock);
+ goto no_register;
+ }
+ } else
+ list_add_tail(&dp83640->list, &clock->phylist);
+
+ if (clock->chosen && !list_empty(&clock->phylist))
+ recalibrate(clock);
+ else
+ enable_broadcast(dp83640->phydev, clock->page, 1);
+
+ dp83640_clock_put(clock);
+ return 0;
+
+no_register:
+ clock->chosen = NULL;
+ kfree(dp83640);
+no_memory:
+ dp83640_clock_put(clock);
+no_clock:
+ return err;
+}
+
+static void dp83640_remove(struct phy_device *phydev)
+{
+ struct dp83640_clock *clock;
+ struct list_head *this, *next;
+ struct dp83640_private *tmp, *dp83640 = phydev->priv;
+
+ if (phydev->addr == BROADCAST_ADDR)
+ return;
+
+ enable_status_frames(phydev, false);
+ cancel_work_sync(&dp83640->ts_work);
+
+ clock = dp83640_clock_get(dp83640->clock);
+
+ if (dp83640 == clock->chosen) {
+ ptp_clock_unregister(clock->ptp_clock);
+ clock->chosen = NULL;
+ } else {
+ list_for_each_safe(this, next, &clock->phylist) {
+ tmp = list_entry(this, struct dp83640_private, list);
+ if (tmp == dp83640) {
+ list_del_init(&tmp->list);
+ break;
+ }
+ }
+ }
+
+ dp83640_clock_put(clock);
+ kfree(dp83640);
+}
+
+static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
+{
+ struct dp83640_private *dp83640 = phydev->priv;
+ struct hwtstamp_config cfg;
+ u16 txcfg0, rxcfg0;
+
+ if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+ return -EFAULT;
+
+ if (cfg.flags) /* reserved for future extensions */
+ return -EINVAL;
+
+ switch (cfg.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ dp83640->hwts_tx_en = 0;
+ break;
+ case HWTSTAMP_TX_ON:
+ dp83640->hwts_tx_en = 1;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (cfg.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ dp83640->hwts_rx_en = 0;
+ dp83640->layer = 0;
+ dp83640->version = 0;
+ break;
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ dp83640->hwts_rx_en = 1;
+ dp83640->layer = LAYER4;
+ dp83640->version = 1;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ dp83640->hwts_rx_en = 1;
+ dp83640->layer = LAYER4;
+ dp83640->version = 2;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ dp83640->hwts_rx_en = 1;
+ dp83640->layer = LAYER2;
+ dp83640->version = 2;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ dp83640->hwts_rx_en = 1;
+ dp83640->layer = LAYER4|LAYER2;
+ dp83640->version = 2;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ txcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
+ rxcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
+
+ if (dp83640->layer & LAYER2) {
+ txcfg0 |= TX_L2_EN;
+ rxcfg0 |= RX_L2_EN;
+ }
+ if (dp83640->layer & LAYER4) {
+ txcfg0 |= TX_IPV6_EN | TX_IPV4_EN;
+ rxcfg0 |= RX_IPV6_EN | RX_IPV4_EN;
+ }
+
+ if (dp83640->hwts_tx_en)
+ txcfg0 |= TX_TS_EN;
+
+ if (dp83640->hwts_rx_en)
+ rxcfg0 |= RX_TS_EN;
+
+ mutex_lock(&dp83640->clock->extreg_lock);
+
+ if (dp83640->hwts_tx_en || dp83640->hwts_rx_en) {
+ enable_status_frames(phydev, true);
+ ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE);
+ }
+
+ ext_write(0, phydev, PAGE5, PTP_TXCFG0, txcfg0);
+ ext_write(0, phydev, PAGE5, PTP_RXCFG0, rxcfg0);
+
+ mutex_unlock(&dp83640->clock->extreg_lock);
+
+ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
+static void rx_timestamp_work(struct work_struct *work)
+{
+ struct dp83640_private *dp83640 =
+ container_of(work, struct dp83640_private, ts_work);
+ struct list_head *this, *next;
+ struct rxts *rxts;
+ struct skb_shared_hwtstamps *shhwtstamps;
+ struct sk_buff *skb;
+ unsigned int type;
+ unsigned long flags;
+
+ /* Deliver each deferred packet, with or without a time stamp. */
+
+ while ((skb = skb_dequeue(&dp83640->rx_queue)) != NULL) {
+ type = SKB_PTP_TYPE(skb);
+ spin_lock_irqsave(&dp83640->rx_lock, flags);
+ list_for_each_safe(this, next, &dp83640->rxts) {
+ rxts = list_entry(this, struct rxts, list);
+ if (match(skb, type, rxts)) {
+ shhwtstamps = skb_hwtstamps(skb);
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+ shhwtstamps->hwtstamp = ns_to_ktime(rxts->ns);
+ list_del_init(&rxts->list);
+ list_add(&rxts->list, &dp83640->rxpool);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&dp83640->rx_lock, flags);
+ netif_rx(skb);
+ }
+
+ /* Clear out expired time stamps. */
+
+ spin_lock_irqsave(&dp83640->rx_lock, flags);
+ prune_rx_ts(dp83640);
+ spin_unlock_irqrestore(&dp83640->rx_lock, flags);
+}
+
+static bool dp83640_rxtstamp(struct phy_device *phydev,
+ struct sk_buff *skb, int type)
+{
+ struct dp83640_private *dp83640 = phydev->priv;
+
+ if (!dp83640->hwts_rx_en)
+ return false;
+
+ if (is_status_frame(skb, type)) {
+ decode_status_frame(dp83640, skb);
+ /* Let the stack drop this frame. */
+ return false;
+ }
+
+ SKB_PTP_TYPE(skb) = type;
+ skb_queue_tail(&dp83640->rx_queue, skb);
+ schedule_work(&dp83640->ts_work);
+
+ return true;
+}
+
+static void dp83640_txtstamp(struct phy_device *phydev,
+ struct sk_buff *skb, int type)
+{
+ struct dp83640_private *dp83640 = phydev->priv;
+
+ if (!dp83640->hwts_tx_en) {
+ kfree_skb(skb);
+ return;
+ }
+ skb_queue_tail(&dp83640->tx_queue, skb);
+ schedule_work(&dp83640->ts_work);
+}
+
+static struct phy_driver dp83640_driver = {
+ .phy_id = DP83640_PHY_ID,
+ .phy_id_mask = 0xfffffff0,
+ .name = "NatSemi DP83640",
+ .features = PHY_BASIC_FEATURES,
+ .flags = 0,
+ .probe = dp83640_probe,
+ .remove = dp83640_remove,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .hwtstamp = dp83640_hwtstamp,
+ .rxtstamp = dp83640_rxtstamp,
+ .txtstamp = dp83640_txtstamp,
+ .driver = {.owner = THIS_MODULE,}
+};
+
+static int __init dp83640_init(void)
+{
+ return phy_driver_register(&dp83640_driver);
+}
+
+static void __exit dp83640_exit(void)
+{
+ dp83640_free_clocks();
+ phy_driver_unregister(&dp83640_driver);
+}
+
+MODULE_DESCRIPTION("National Semiconductor DP83640 PHY driver");
+MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>");
+MODULE_LICENSE("GPL");
+
+module_init(dp83640_init);
+module_exit(dp83640_exit);
+
+static struct mdio_device_id dp83640_tbl[] = {
+ { DP83640_PHY_ID, 0xfffffff0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(mdio, dp83640_tbl);
diff --git a/drivers/net/phy/dp83640_reg.h b/drivers/net/phy/dp83640_reg.h
new file mode 100644
index 0000000..e7fe411
--- /dev/null
+++ b/drivers/net/phy/dp83640_reg.h
@@ -0,0 +1,267 @@
+/* dp83640_reg.h
+ * Generated by regen.tcl on Thu Feb 17 10:02:48 AM CET 2011
+ */
+#ifndef HAVE_DP83640_REGISTERS
+#define HAVE_DP83640_REGISTERS
+
+#define PAGE0 0x0000
+#define PHYCR2 0x001c /* PHY Control Register 2 */
+
+#define PAGE4 0x0004
+#define PTP_CTL 0x0014 /* PTP Control Register */
+#define PTP_TDR 0x0015 /* PTP Time Data Register */
+#define PTP_STS 0x0016 /* PTP Status Register */
+#define PTP_TSTS 0x0017 /* PTP Trigger Status Register */
+#define PTP_RATEL 0x0018 /* PTP Rate Low Register */
+#define PTP_RATEH 0x0019 /* PTP Rate High Register */
+#define PTP_RDCKSUM 0x001a /* PTP Read Checksum */
+#define PTP_WRCKSUM 0x001b /* PTP Write Checksum */
+#define PTP_TXTS 0x001c /* PTP Transmit Timestamp Register, in four 16-bit reads */
+#define PTP_RXTS 0x001d /* PTP Receive Timestamp Register, in six? 16-bit reads */
+#define PTP_ESTS 0x001e /* PTP Event Status Register */
+#define PTP_EDATA 0x001f /* PTP Event Data Register */
+
+#define PAGE5 0x0005
+#define PTP_TRIG 0x0014 /* PTP Trigger Configuration Register */
+#define PTP_EVNT 0x0015 /* PTP Event Configuration Register */
+#define PTP_TXCFG0 0x0016 /* PTP Transmit Configuration Register 0 */
+#define PTP_TXCFG1 0x0017 /* PTP Transmit Configuration Register 1 */
+#define PSF_CFG0 0x0018 /* PHY Status Frame Configuration Register 0 */
+#define PTP_RXCFG0 0x0019 /* PTP Receive Configuration Register 0 */
+#define PTP_RXCFG1 0x001a /* PTP Receive Configuration Register 1 */
+#define PTP_RXCFG2 0x001b /* PTP Receive Configuration Register 2 */
+#define PTP_RXCFG3 0x001c /* PTP Receive Configuration Register 3 */
+#define PTP_RXCFG4 0x001d /* PTP Receive Configuration Register 4 */
+#define PTP_TRDL 0x001e /* PTP Temporary Rate Duration Low Register */
+#define PTP_TRDH 0x001f /* PTP Temporary Rate Duration High Register */
+
+#define PAGE6 0x0006
+#define PTP_COC 0x0014 /* PTP Clock Output Control Register */
+#define PSF_CFG1 0x0015 /* PHY Status Frame Configuration Register 1 */
+#define PSF_CFG2 0x0016 /* PHY Status Frame Configuration Register 2 */
+#define PSF_CFG3 0x0017 /* PHY Status Frame Configuration Register 3 */
+#define PSF_CFG4 0x0018 /* PHY Status Frame Configuration Register 4 */
+#define PTP_SFDCFG 0x0019 /* PTP SFD Configuration Register */
+#define PTP_INTCTL 0x001a /* PTP Interrupt Control Register */
+#define PTP_CLKSRC 0x001b /* PTP Clock Source Register */
+#define PTP_ETR 0x001c /* PTP Ethernet Type Register */
+#define PTP_OFF 0x001d /* PTP Offset Register */
+#define PTP_GPIOMON 0x001e /* PTP GPIO Monitor Register */
+#define PTP_RXHASH 0x001f /* PTP Receive Hash Register */
+
+/* Bit definitions for the PHYCR2 register */
+#define BC_WRITE (1<<11) /* Broadcast Write Enable */
+
+/* Bit definitions for the PTP_CTL register */
+#define TRIG_SEL_SHIFT (10) /* PTP Trigger Select */
+#define TRIG_SEL_MASK (0x7)
+#define TRIG_DIS (1<<9) /* Disable PTP Trigger */
+#define TRIG_EN (1<<8) /* Enable PTP Trigger */
+#define TRIG_READ (1<<7) /* Read PTP Trigger */
+#define TRIG_LOAD (1<<6) /* Load PTP Trigger */
+#define PTP_RD_CLK (1<<5) /* Read PTP Clock */
+#define PTP_LOAD_CLK (1<<4) /* Load PTP Clock */
+#define PTP_STEP_CLK (1<<3) /* Step PTP Clock */
+#define PTP_ENABLE (1<<2) /* Enable PTP Clock */
+#define PTP_DISABLE (1<<1) /* Disable PTP Clock */
+#define PTP_RESET (1<<0) /* Reset PTP Clock */
+
+/* Bit definitions for the PTP_STS register */
+#define TXTS_RDY (1<<11) /* Transmit Timestamp Ready */
+#define RXTS_RDY (1<<10) /* Receive Timestamp Ready */
+#define TRIG_DONE (1<<9) /* PTP Trigger Done */
+#define EVENT_RDY (1<<8) /* PTP Event Timestamp Ready */
+#define TXTS_IE (1<<3) /* Transmit Timestamp Interrupt Enable */
+#define RXTS_IE (1<<2) /* Receive Timestamp Interrupt Enable */
+#define TRIG_IE (1<<1) /* Trigger Interrupt Enable */
+#define EVENT_IE (1<<0) /* Event Interrupt Enable */
+
+/* Bit definitions for the PTP_TSTS register */
+#define TRIG7_ERROR (1<<15) /* Trigger 7 Error */
+#define TRIG7_ACTIVE (1<<14) /* Trigger 7 Active */
+#define TRIG6_ERROR (1<<13) /* Trigger 6 Error */
+#define TRIG6_ACTIVE (1<<12) /* Trigger 6 Active */
+#define TRIG5_ERROR (1<<11) /* Trigger 5 Error */
+#define TRIG5_ACTIVE (1<<10) /* Trigger 5 Active */
+#define TRIG4_ERROR (1<<9) /* Trigger 4 Error */
+#define TRIG4_ACTIVE (1<<8) /* Trigger 4 Active */
+#define TRIG3_ERROR (1<<7) /* Trigger 3 Error */
+#define TRIG3_ACTIVE (1<<6) /* Trigger 3 Active */
+#define TRIG2_ERROR (1<<5) /* Trigger 2 Error */
+#define TRIG2_ACTIVE (1<<4) /* Trigger 2 Active */
+#define TRIG1_ERROR (1<<3) /* Trigger 1 Error */
+#define TRIG1_ACTIVE (1<<2) /* Trigger 1 Active */
+#define TRIG0_ERROR (1<<1) /* Trigger 0 Error */
+#define TRIG0_ACTIVE (1<<0) /* Trigger 0 Active */
+
+/* Bit definitions for the PTP_RATEH register */
+#define PTP_RATE_DIR (1<<15) /* PTP Rate Direction */
+#define PTP_TMP_RATE (1<<14) /* PTP Temporary Rate */
+#define PTP_RATE_HI_SHIFT (0) /* PTP Rate High 10-bits */
+#define PTP_RATE_HI_MASK (0x3ff)
+
+/* Bit definitions for the PTP_ESTS register */
+#define EVNTS_MISSED_SHIFT (8) /* Indicates number of events missed */
+#define EVNTS_MISSED_MASK (0x7)
+#define EVNT_TS_LEN_SHIFT (6) /* Indicates length of the Timestamp field in 16-bit words minus 1 */
+#define EVNT_TS_LEN_MASK (0x3)
+#define EVNT_RF (1<<5) /* Indicates whether the event is a rise or falling event */
+#define EVNT_NUM_SHIFT (2) /* Indicates Event Timestamp Unit which detected an event */
+#define EVNT_NUM_MASK (0x7)
+#define MULT_EVNT (1<<1) /* Indicates multiple events were detected at the same time */
+#define EVENT_DET (1<<0) /* PTP Event Detected */
+
+/* Bit definitions for the PTP_EDATA register */
+#define E7_RISE (1<<15) /* Indicates direction of Event 7 */
+#define E7_DET (1<<14) /* Indicates Event 7 detected */
+#define E6_RISE (1<<13) /* Indicates direction of Event 6 */
+#define E6_DET (1<<12) /* Indicates Event 6 detected */
+#define E5_RISE (1<<11) /* Indicates direction of Event 5 */
+#define E5_DET (1<<10) /* Indicates Event 5 detected */
+#define E4_RISE (1<<9) /* Indicates direction of Event 4 */
+#define E4_DET (1<<8) /* Indicates Event 4 detected */
+#define E3_RISE (1<<7) /* Indicates direction of Event 3 */
+#define E3_DET (1<<6) /* Indicates Event 3 detected */
+#define E2_RISE (1<<5) /* Indicates direction of Event 2 */
+#define E2_DET (1<<4) /* Indicates Event 2 detected */
+#define E1_RISE (1<<3) /* Indicates direction of Event 1 */
+#define E1_DET (1<<2) /* Indicates Event 1 detected */
+#define E0_RISE (1<<1) /* Indicates direction of Event 0 */
+#define E0_DET (1<<0) /* Indicates Event 0 detected */
+
+/* Bit definitions for the PTP_TRIG register */
+#define TRIG_PULSE (1<<15) /* generate a Pulse rather than a single edge */
+#define TRIG_PER (1<<14) /* generate a periodic signal */
+#define TRIG_IF_LATE (1<<13) /* trigger immediately if already past */
+#define TRIG_NOTIFY (1<<12) /* Trigger Notification Enable */
+#define TRIG_GPIO_SHIFT (8) /* Trigger GPIO Connection, value 1-12 */
+#define TRIG_GPIO_MASK (0xf)
+#define TRIG_TOGGLE (1<<7) /* Trigger Toggle Mode Enable */
+#define TRIG_CSEL_SHIFT (1) /* Trigger Configuration Select */
+#define TRIG_CSEL_MASK (0x7)
+#define TRIG_WR (1<<0) /* Trigger Configuration Write */
+
+/* Bit definitions for the PTP_EVNT register */
+#define EVNT_RISE (1<<14) /* Event Rise Detect Enable */
+#define EVNT_FALL (1<<13) /* Event Fall Detect Enable */
+#define EVNT_SINGLE (1<<12) /* enable single event capture operation */
+#define EVNT_GPIO_SHIFT (8) /* Event GPIO Connection, value 1-12 */
+#define EVNT_GPIO_MASK (0xf)
+#define EVNT_SEL_SHIFT (1) /* Event Select */
+#define EVNT_SEL_MASK (0x7)
+#define EVNT_WR (1<<0) /* Event Configuration Write */
+
+/* Bit definitions for the PTP_TXCFG0 register */
+#define SYNC_1STEP (1<<15) /* insert timestamp into transmit Sync Messages */
+#define DR_INSERT (1<<13) /* Insert Delay_Req Timestamp in Delay_Resp (dangerous) */
+#define NTP_TS_EN (1<<12) /* Enable Timestamping of NTP Packets */
+#define IGNORE_2STEP (1<<11) /* Ignore Two_Step flag for One-Step operation */
+#define CRC_1STEP (1<<10) /* Disable checking of CRC for One-Step operation */
+#define CHK_1STEP (1<<9) /* Enable UDP Checksum correction for One-Step Operation */
+#define IP1588_EN (1<<8) /* Enable IEEE 1588 defined IP address filter */
+#define TX_L2_EN (1<<7) /* Layer2 Timestamp Enable */
+#define TX_IPV6_EN (1<<6) /* IPv6 Timestamp Enable */
+#define TX_IPV4_EN (1<<5) /* IPv4 Timestamp Enable */
+#define TX_PTP_VER_SHIFT (1) /* Enable Timestamp capture for IEEE 1588 version X */
+#define TX_PTP_VER_MASK (0xf)
+#define TX_TS_EN (1<<0) /* Transmit Timestamp Enable */
+
+/* Bit definitions for the PTP_TXCFG1 register */
+#define BYTE0_MASK_SHIFT (8) /* Bit mask to be used for matching Byte0 of the PTP Message */
+#define BYTE0_MASK_MASK (0xff)
+#define BYTE0_DATA_SHIFT (0) /* Data to be used for matching Byte0 of the PTP Message */
+#define BYTE0_DATA_MASK (0xff)
+
+/* Bit definitions for the PSF_CFG0 register */
+#define MAC_SRC_ADD_SHIFT (11) /* Status Frame Mac Source Address */
+#define MAC_SRC_ADD_MASK (0x3)
+#define MIN_PRE_SHIFT (8) /* Status Frame Minimum Preamble */
+#define MIN_PRE_MASK (0x7)
+#define PSF_ENDIAN (1<<7) /* Status Frame Endian Control */
+#define PSF_IPV4 (1<<6) /* Status Frame IPv4 Enable */
+#define PSF_PCF_RD (1<<5) /* Control Frame Read PHY Status Frame Enable */
+#define PSF_ERR_EN (1<<4) /* Error PHY Status Frame Enable */
+#define PSF_TXTS_EN (1<<3) /* Transmit Timestamp PHY Status Frame Enable */
+#define PSF_RXTS_EN (1<<2) /* Receive Timestamp PHY Status Frame Enable */
+#define PSF_TRIG_EN (1<<1) /* Trigger PHY Status Frame Enable */
+#define PSF_EVNT_EN (1<<0) /* Event PHY Status Frame Enable */
+
+/* Bit definitions for the PTP_RXCFG0 register */
+#define DOMAIN_EN (1<<15) /* Domain Match Enable */
+#define ALT_MAST_DIS (1<<14) /* Alternate Master Timestamp Disable */
+#define USER_IP_SEL (1<<13) /* Selects portion of IP address accessible thru PTP_RXCFG2 */
+#define USER_IP_EN (1<<12) /* Enable User-programmed IP address filter */
+#define RX_SLAVE (1<<11) /* Receive Slave Only */
+#define IP1588_EN_SHIFT (8) /* Enable IEEE 1588 defined IP address filters */
+#define IP1588_EN_MASK (0xf)
+#define RX_L2_EN (1<<7) /* Layer2 Timestamp Enable */
+#define RX_IPV6_EN (1<<6) /* IPv6 Timestamp Enable */
+#define RX_IPV4_EN (1<<5) /* IPv4 Timestamp Enable */
+#define RX_PTP_VER_SHIFT (1) /* Enable Timestamp capture for IEEE 1588 version X */
+#define RX_PTP_VER_MASK (0xf)
+#define RX_TS_EN (1<<0) /* Receive Timestamp Enable */
+
+/* Bit definitions for the PTP_RXCFG1 register */
+#define BYTE0_MASK_SHIFT (8) /* Bit mask to be used for matching Byte0 of the PTP Message */
+#define BYTE0_MASK_MASK (0xff)
+#define BYTE0_DATA_SHIFT (0) /* Data to be used for matching Byte0 of the PTP Message */
+#define BYTE0_DATA_MASK (0xff)
+
+/* Bit definitions for the PTP_RXCFG3 register */
+#define TS_MIN_IFG_SHIFT (12) /* Minimum Inter-frame Gap */
+#define TS_MIN_IFG_MASK (0xf)
+#define ACC_UDP (1<<11) /* Record Timestamp if UDP Checksum Error */
+#define ACC_CRC (1<<10) /* Record Timestamp if CRC Error */
+#define TS_APPEND (1<<9) /* Append Timestamp for L2 */
+#define TS_INSERT (1<<8) /* Enable Timestamp Insertion */
+#define PTP_DOMAIN_SHIFT (0) /* PTP Message domainNumber field */
+#define PTP_DOMAIN_MASK (0xff)
+
+/* Bit definitions for the PTP_RXCFG4 register */
+#define IPV4_UDP_MOD (1<<15) /* Enable IPV4 UDP Modification */
+#define TS_SEC_EN (1<<14) /* Enable Timestamp Seconds */
+#define TS_SEC_LEN_SHIFT (12) /* Inserted Timestamp Seconds Length */
+#define TS_SEC_LEN_MASK (0x3)
+#define RXTS_NS_OFF_SHIFT (6) /* Receive Timestamp Nanoseconds offset */
+#define RXTS_NS_OFF_MASK (0x3f)
+#define RXTS_SEC_OFF_SHIFT (0) /* Receive Timestamp Seconds offset */
+#define RXTS_SEC_OFF_MASK (0x3f)
+
+/* Bit definitions for the PTP_COC register */
+#define PTP_CLKOUT_EN (1<<15) /* PTP Clock Output Enable */
+#define PTP_CLKOUT_SEL (1<<14) /* PTP Clock Output Source Select */
+#define PTP_CLKOUT_SPEEDSEL (1<<13) /* PTP Clock Output I/O Speed Select */
+#define PTP_CLKDIV_SHIFT (0) /* PTP Clock Divide-by Value */
+#define PTP_CLKDIV_MASK (0xff)
+
+/* Bit definitions for the PSF_CFG1 register */
+#define PTPRESERVED_SHIFT (12) /* PTP v2 reserved field */
+#define PTPRESERVED_MASK (0xf)
+#define VERSIONPTP_SHIFT (8) /* PTP v2 versionPTP field */
+#define VERSIONPTP_MASK (0xf)
+#define TRANSPORT_SPECIFIC_SHIFT (4) /* PTP v2 Header transportSpecific field */
+#define TRANSPORT_SPECIFIC_MASK (0xf)
+#define MESSAGETYPE_SHIFT (0) /* PTP v2 messageType field */
+#define MESSAGETYPE_MASK (0xf)
+
+/* Bit definitions for the PTP_SFDCFG register */
+#define TX_SFD_GPIO_SHIFT (4) /* TX SFD GPIO Select, value 1-12 */
+#define TX_SFD_GPIO_MASK (0xf)
+#define RX_SFD_GPIO_SHIFT (0) /* RX SFD GPIO Select, value 1-12 */
+#define RX_SFD_GPIO_MASK (0xf)
+
+/* Bit definitions for the PTP_INTCTL register */
+#define PTP_INT_GPIO_SHIFT (0) /* PTP Interrupt GPIO Select */
+#define PTP_INT_GPIO_MASK (0xf)
+
+/* Bit definitions for the PTP_CLKSRC register */
+#define CLK_SRC_SHIFT (14) /* PTP Clock Source Select */
+#define CLK_SRC_MASK (0x3)
+#define CLK_SRC_PER_SHIFT (0) /* PTP Clock Source Period */
+#define CLK_SRC_PER_MASK (0x7f)
+
+/* Bit definitions for the PTP_OFF register */
+#define PTP_OFFSET_SHIFT (0) /* PTP Message offset from preceding header */
+#define PTP_OFFSET_MASK (0xff)
+
+#endif
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index fcfafd0..68d7201 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -53,4 +53,23 @@ config PTP_1588_CLOCK_IXP46X
To compile this driver as a module, choose M here: the module
will be called ptp_ixp46x.
+comment "Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks."
+ depends on PTP_1588_CLOCK && (PHYLIB=n || NETWORK_PHY_TIMESTAMPING=n)
+
+config DP83640_PHY
+ tristate "Driver for the National Semiconductor DP83640 PHYTER"
+ depends on PTP_1588_CLOCK
+ depends on NETWORK_PHY_TIMESTAMPING
+ depends on PHYLIB
+ ---help---
+ Supports the DP83640 PHYTER with IEEE 1588 features.
+
+ This driver adds support for using the DP83640 as a PTP
+ clock. This clock is only useful if your PTP programs are
+ getting hardware time stamps on the PTP Ethernet packets
+ using the SO_TIMESTAMPING API.
+
+ In order for this to work, your MAC driver must also
+ implement the skb_tx_timetamp() function.
+
endmenu
--
1.7.0.4
^ 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