Re: ARM Ftrace Function Graph Fails With UNWINDER_FRAME_POINTER

2023-12-02 Thread Justin Chen



On 12/2/2023 1:26 AM, Ard Biesheuvel wrote:

On Sat, 2 Dec 2023 at 09:49, Justin Chen  wrote:




On 12/1/23 10:53 PM, Ard Biesheuvel wrote:

On Fri, 1 Dec 2023 at 23:59, Justin Chen  wrote:




On 12/1/23 10:07 AM, Steven Rostedt wrote:

On Fri, 1 Dec 2023 09:25:59 -0800
Justin Chen  wrote:


It appears the sub instruction at 0x6dd0 correctly accounts for the
extra 8 bytes, so the frame pointer is valid. So it is our assumption
that there are no gaps between the stack frames is invalid.


Thanks for the assistance. The gap between the stack frame depends on
the function. Most do not have a gap. Some have 8 (as shown above), some
have 12. A single assumption here is not going to work. I'm having a
hard time finding out the reasoning for this gap. I tried disabling a
bunch of gcc flags as well as -O2 and the gap still exists.


That code was originally added because of some strange things that gcc did
with mcount (for example, it made a copy of the stack frame that it passed
to mcount, where the function graph tracer replaced the copy of the return
stack making the shadow stack go out of sync and crash). This was very hard
to debug and I added this code to detect it if it happened again.

Well it's been over a decade since that happened (2009).

 71e308a239c09 ("function-graph: add stack frame test")

I'm happy assuming that the compiler folks are aware of our tricks with
hijacking return calls and I don't expect it to happen again. We can just
rip out those checks. That is, if it's only causing false positives, I
don't think it's worth keeping around.

Has it detected any real issues on the Arm platforms?

-- Steve


I am not familiar enough to make a call. But from my limited testing
with ARM, I didn't see any issues. If you would like me to, I can submit
a patch to remove the check entirely. Or maybe only disable it for ARM?



Please try the fix I proposed first.


Just tested it. Seems to do the trick.


Thanks


Either solution works for me.



Given that this discussion is taking place in the context of the
report of an issue identified by GRAPH_FP_TEST, I don't see how
removing that would be a reasonable conclusion.



Fair enough. I will submit a patch. Thanks for the help.


FWIW I also experimented with LLVM, looks like function_graph just
crashes regardless of the issue being discussed. The disassemble of
LLVM[1] does something completely different.




LLVM does not support CONFIG_UNWINDER_FRAME_POINTER so the fact that
the prologue looks different is expected.

In the case below, the FP {r11} is correctly made to point to a {r11,
lr} tuple on the stack, so the codegen is correct AFAICT. But IIRC we
rely on unwind information for ftrace in this case, not the frame
pointer.

Could you be more specific about the crash?



It just hangs with no prints. I can instrument the hang and see what I 
can find.


Justin





[1]
LLVM dump
c0c6faa0 :
c0c6faa0: f0 4f 2d e9   push{r4, r5, r6, r7, r8, r9, r10, r11, lr}
c0c6faa4: 1c b0 8d e2   add r11, sp, #28
c0c6faa8: ac d0 4d e2   sub sp, sp, #172
c0c6faac: 00 70 a0 e1   mov r7, r0
c0c6fab0: c8 0c 04 e3   movwr0, #19656
c0c6fab4: 80 02 4c e3   movtr0, #49792
c0c6fab8: 03 50 a0 e1   mov r5, r3
c0c6fabc: 00 00 90 e5   ldr r0, [r0]
c0c6fac0: 02 a0 a0 e1   mov r10, r2
c0c6fac4: 20 00 0b e5   str r0, [r11, #-32]
c0c6fac8: 00 40 2d e9   stmdb   sp!, {lr}
c0c6facc: 4b 8b d6 eb   bl  0xc0212800 <__gnu_mcount_nc> @ imm =
#-10867412


smime.p7s
Description: S/MIME Cryptographic Signature


Re: ARM Ftrace Function Graph Fails With UNWINDER_FRAME_POINTER

2023-12-02 Thread Justin Chen



On 12/1/23 10:53 PM, Ard Biesheuvel wrote:

On Fri, 1 Dec 2023 at 23:59, Justin Chen  wrote:




On 12/1/23 10:07 AM, Steven Rostedt wrote:

On Fri, 1 Dec 2023 09:25:59 -0800
Justin Chen  wrote:


It appears the sub instruction at 0x6dd0 correctly accounts for the
extra 8 bytes, so the frame pointer is valid. So it is our assumption
that there are no gaps between the stack frames is invalid.


Thanks for the assistance. The gap between the stack frame depends on
the function. Most do not have a gap. Some have 8 (as shown above), some
have 12. A single assumption here is not going to work. I'm having a
hard time finding out the reasoning for this gap. I tried disabling a
bunch of gcc flags as well as -O2 and the gap still exists.


That code was originally added because of some strange things that gcc did
with mcount (for example, it made a copy of the stack frame that it passed
to mcount, where the function graph tracer replaced the copy of the return
stack making the shadow stack go out of sync and crash). This was very hard
to debug and I added this code to detect it if it happened again.

Well it's been over a decade since that happened (2009).

71e308a239c09 ("function-graph: add stack frame test")

I'm happy assuming that the compiler folks are aware of our tricks with
hijacking return calls and I don't expect it to happen again. We can just
rip out those checks. That is, if it's only causing false positives, I
don't think it's worth keeping around.

Has it detected any real issues on the Arm platforms?

-- Steve


I am not familiar enough to make a call. But from my limited testing
with ARM, I didn't see any issues. If you would like me to, I can submit
a patch to remove the check entirely. Or maybe only disable it for ARM?



Please try the fix I proposed first.


Just tested it. Seems to do the trick. Either solution works for me.

FWIW I also experimented with LLVM, looks like function_graph just 
crashes regardless of the issue being discussed. The disassemble of 
LLVM[1] does something completely different.


Thanks,
Justin

[1]
LLVM dump
c0c6faa0 :
c0c6faa0: f0 4f 2d e9   push{r4, r5, r6, r7, r8, r9, r10, r11, lr}
c0c6faa4: 1c b0 8d e2   add r11, sp, #28
c0c6faa8: ac d0 4d e2   sub sp, sp, #172
c0c6faac: 00 70 a0 e1   mov r7, r0
c0c6fab0: c8 0c 04 e3   movwr0, #19656
c0c6fab4: 80 02 4c e3   movtr0, #49792
c0c6fab8: 03 50 a0 e1   mov r5, r3
c0c6fabc: 00 00 90 e5   ldr r0, [r0]
c0c6fac0: 02 a0 a0 e1   mov r10, r2
c0c6fac4: 20 00 0b e5   str r0, [r11, #-32]
c0c6fac8: 00 40 2d e9   stmdb   sp!, {lr}
c0c6facc: 4b 8b d6 eb   bl  0xc0212800 <__gnu_mcount_nc> @ imm = 
#-10867412


smime.p7s
Description: S/MIME Cryptographic Signature


Re: ARM Ftrace Function Graph Fails With UNWINDER_FRAME_POINTER

2023-12-01 Thread Justin Chen



On 12/1/23 10:07 AM, Steven Rostedt wrote:

On Fri, 1 Dec 2023 09:25:59 -0800
Justin Chen  wrote:


It appears the sub instruction at 0x6dd0 correctly accounts for the
extra 8 bytes, so the frame pointer is valid. So it is our assumption
that there are no gaps between the stack frames is invalid.


Thanks for the assistance. The gap between the stack frame depends on
the function. Most do not have a gap. Some have 8 (as shown above), some
have 12. A single assumption here is not going to work. I'm having a
hard time finding out the reasoning for this gap. I tried disabling a
bunch of gcc flags as well as -O2 and the gap still exists.


That code was originally added because of some strange things that gcc did
with mcount (for example, it made a copy of the stack frame that it passed
to mcount, where the function graph tracer replaced the copy of the return
stack making the shadow stack go out of sync and crash). This was very hard
to debug and I added this code to detect it if it happened again.

Well it's been over a decade since that happened (2009).

   71e308a239c09 ("function-graph: add stack frame test")

I'm happy assuming that the compiler folks are aware of our tricks with
hijacking return calls and I don't expect it to happen again. We can just
rip out those checks. That is, if it's only causing false positives, I
don't think it's worth keeping around.

Has it detected any real issues on the Arm platforms?

-- Steve


I am not familiar enough to make a call. But from my limited testing 
with ARM, I didn't see any issues. If you would like me to, I can submit 
a patch to remove the check entirely. Or maybe only disable it for ARM?


Thanks,
Justin


smime.p7s
Description: S/MIME Cryptographic Signature


Re: ARM Ftrace Function Graph Fails With UNWINDER_FRAME_POINTER

2023-12-01 Thread Justin Chen



On 12/1/2023 1:12 AM, Ard Biesheuvel wrote:

On Fri, 1 Dec 2023 at 00:48, Justin Chen  wrote:


Hello,

Ran into an odd bug that I am unsure what the solution is. Tested a few
kernels versions and they all fail the same.

FUNCTION_GRAPH_FP_TEST was enabled with 953f534a7ed6 ("ARM: ftrace:
enable HAVE_FUNCTION_GRAPH_FP_TEST"). This test fails when
UNWINDER_FRAME_POINTER is enabled. Enable function_graph tracer and you
should see a failure similar to below.

[   63.817239] [ cut here ]
[   63.822006] WARNING: CPU: 3 PID: 1185 at kernel/trace/fgraph.c:195
ftrace_return_to_handler+0x228/0x374
[   63.831645] Bad frame pointer: expected d1e0df40, received d1e0df48
[   63.831645]   from func packet_setsockopt return to c0b558f4
[   63.843801] Modules linked in: bdc udc_core
[   63.848246] CPU: 3 PID: 1185 Comm: udhcpc Not tainted
6.1.53-0.1pre-gf0bc552d12f8 #33
[   63.856209] Hardware name: Broadcom STB (Flattened Device Tree)
[   63.862227] Backtrace:
[   63.864761]  dump_backtrace from show_stack+0x20/0x24
[   63.869982]  r7:c031cd8c r6:0009 r5:0013 r4:c11c7fac
[   63.875736]  show_stack from dump_stack_lvl+0x48/0x54
[   63.880929]  dump_stack_lvl from dump_stack+0x18/0x1c
[   63.886111]  r5:00c3 r4:c11bd92c
[   63.889764]  dump_stack from __warn+0x88/0x130
[   63.894339]  __warn from warn_slowpath_fmt+0x140/0x198
[   63.899631]  r8:d1e0deac r7:c11bd958 r6:c031cd8c r5:c11bd92c r4:
[   63.906431]  warn_slowpath_fmt from ftrace_return_to_handler+0x228/0x374
[   63.913294]  r8:c3a8d840 r7:0002 r6:d1e0df48 r5:c2377a94 r4:c269a400
[   63.920095]  ftrace_return_to_handler from return_to_handler+0xc/0x18
[   63.926699]  r8:c0cd8ed0 r7:0008 r6:c418c500 r5:0004 r4:0107
[   63.933500]  __sys_setsockopt from return_to_handler+0x0/0x18
[   63.939415]  r8:c02002bc r7:0126 r6:0003 r5: r4:0004
[   63.946217]  sys_setsockopt from return_to_handler+0x0/0x18
[   63.952053] ---[ end trace  ]---

Sure enough the top of the parent stack is off by 8. (Tested with
gcc6.3/gcc8.3/gcc12.3)
6dcc :
  6dcc:   e1a0c00dmov ip, sp
  6dd0:   e24dd008sub sp, sp, #8 <==
  6dd4:   e92ddff0push{r4, r5, r6, r7, r8, r9, sl,
fp, ip, lr, pc}
  6dd8:   e24cb00csub fp, ip, #12
  6ddc:   e24dd06csub sp, sp, #108@ 0x6c
  6de0:   e52de004push{lr}@ (str lr, [sp,
#-4]!)
  6de4:   ebfebl  0 <__gnu_mcount_nc>

I'm not quite sure why gcc is putting this extra 8 byte frame (maybe
some optimization?), but it isn't being accounted for thus the
FUNCTION_GRAPH_FP_TEST for arm fails. Note that only some functions do
this. Function graph works with FUNCTION_GRAPH_FP_TEST disabled, so it
looks the test is hitting false positives.



Thanks for the report.

It appears the sub instruction at 0x6dd0 correctly accounts for the
extra 8 bytes, so the frame pointer is valid. So it is our assumption
that there are no gaps between the stack frames is invalid.


Thanks for the assistance. The gap between the stack frame depends on 
the function. Most do not have a gap. Some have 8 (as shown above), some 
have 12. A single assumption here is not going to work. I'm having a 
hard time finding out the reasoning for this gap. I tried disabling a 
bunch of gcc flags as well as -O2 and the gap still exists.


Thanks,
Justin



Could you try the following change please?

--- a/arch/arm/kernel/ftrace.c
+++ b/arch/arm/kernel/ftrace.c
@@ -235,8 +235,12 @@
 return;

 if (IS_ENABLED(CONFIG_UNWINDER_FRAME_POINTER)) {
-   /* FP points one word below parent's top of stack */
-   frame_pointer += 4;
+   /*
+* The top of stack of the parent is recorded in the stack
+* frame at offset [fp, #-8].
+*/
+   get_kernel_nofault(frame_pointer,
+  (unsigned long *)(frame_pointer - 8));
 } else {
 struct stackframe frame = {
 .fp = frame_pointer,


smime.p7s
Description: S/MIME Cryptographic Signature


ARM Ftrace Function Graph Fails With UNWINDER_FRAME_POINTER

2023-11-30 Thread Justin Chen

Hello,

Ran into an odd bug that I am unsure what the solution is. Tested a few 
kernels versions and they all fail the same.


FUNCTION_GRAPH_FP_TEST was enabled with 953f534a7ed6 ("ARM: ftrace: 
enable HAVE_FUNCTION_GRAPH_FP_TEST"). This test fails when 
UNWINDER_FRAME_POINTER is enabled. Enable function_graph tracer and you 
should see a failure similar to below.


[   63.817239] [ cut here ]
[   63.822006] WARNING: CPU: 3 PID: 1185 at kernel/trace/fgraph.c:195 
ftrace_return_to_handler+0x228/0x374

[   63.831645] Bad frame pointer: expected d1e0df40, received d1e0df48
[   63.831645]   from func packet_setsockopt return to c0b558f4
[   63.843801] Modules linked in: bdc udc_core
[   63.848246] CPU: 3 PID: 1185 Comm: udhcpc Not tainted 
6.1.53-0.1pre-gf0bc552d12f8 #33

[   63.856209] Hardware name: Broadcom STB (Flattened Device Tree)
[   63.862227] Backtrace:
[   63.864761]  dump_backtrace from show_stack+0x20/0x24
[   63.869982]  r7:c031cd8c r6:0009 r5:0013 r4:c11c7fac
[   63.875736]  show_stack from dump_stack_lvl+0x48/0x54
[   63.880929]  dump_stack_lvl from dump_stack+0x18/0x1c
[   63.886111]  r5:00c3 r4:c11bd92c
[   63.889764]  dump_stack from __warn+0x88/0x130
[   63.894339]  __warn from warn_slowpath_fmt+0x140/0x198
[   63.899631]  r8:d1e0deac r7:c11bd958 r6:c031cd8c r5:c11bd92c r4:
[   63.906431]  warn_slowpath_fmt from ftrace_return_to_handler+0x228/0x374
[   63.913294]  r8:c3a8d840 r7:0002 r6:d1e0df48 r5:c2377a94 r4:c269a400
[   63.920095]  ftrace_return_to_handler from return_to_handler+0xc/0x18
[   63.926699]  r8:c0cd8ed0 r7:0008 r6:c418c500 r5:0004 r4:0107
[   63.933500]  __sys_setsockopt from return_to_handler+0x0/0x18
[   63.939415]  r8:c02002bc r7:0126 r6:0003 r5: r4:0004
[   63.946217]  sys_setsockopt from return_to_handler+0x0/0x18
[   63.952053] ---[ end trace  ]---

Sure enough the top of the parent stack is off by 8. (Tested with 
gcc6.3/gcc8.3/gcc12.3)

6dcc :
    6dcc:   e1a0c00d    mov ip, sp
    6dd0:   e24dd008    sub sp, sp, #8 <==
    6dd4:   e92ddff0    push    {r4, r5, r6, r7, r8, r9, sl, 
fp, ip, lr, pc}

    6dd8:   e24cb00c    sub fp, ip, #12
    6ddc:   e24dd06c    sub sp, sp, #108    @ 0x6c
    6de0:   e52de004    push    {lr}    @ (str lr, [sp, 
#-4]!)

    6de4:   ebfe    bl  0 <__gnu_mcount_nc>

I'm not quite sure why gcc is putting this extra 8 byte frame (maybe 
some optimization?), but it isn't being accounted for thus the 
FUNCTION_GRAPH_FP_TEST for arm fails. Note that only some functions do 
this. Function graph works with FUNCTION_GRAPH_FP_TEST disabled, so it 
looks the test is hitting false positives.


Thanks,
Justin


smime.p7s
Description: S/MIME Cryptographic Signature


Re: [PATCH] iio: adc: ti-ads7950: Fix build error without CONFIG_GPIOLIB

2019-04-10 Thread Justin Chen
On Wed, Apr 10, 2019 at 1:47 AM Yue Haibing  wrote:
>
> From: YueHaibing 
>
> When building with CONFIG_GPIOLIB is not set
> gcc warns this:
>
> drivers/iio/adc/ti-ads7950.c:75:19: error: field chip has incomplete type
>   struct gpio_chip chip;
>^~~~
> drivers/iio/adc/ti-ads7950.c: In function ti_ads7950_set:
> drivers/iio/adc/ti-ads7950.c:409:32: error: implicit declaration of function 
> gpiochip_get_data; did you mean acpi_get_data? 
> [-Werror=implicit-function-declaration]
>   struct ti_ads7950_state *st = gpiochip_get_data(chip);
> ^
> acpi_get_data
>
> Reported-by: Hulk Robot 
> Fixes: c97dce792dc8 ("iio: adc: ti-ads7950: add GPIO support")
> Signed-off-by: YueHaibing 
Reviewed-by: Justin Chen 

Thanks,
Justin
> ---
>  drivers/iio/adc/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 846c7ac..f760269 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -968,7 +968,7 @@ config TI_ADS1015
>
>  config TI_ADS7950
> tristate "Texas Instruments ADS7950 ADC driver"
> -   depends on SPI
> +   depends on SPI && GPIOLIB
> select IIO_BUFFER
> select IIO_TRIGGERED_BUFFER
> help
> --
> 2.7.4
>
>


Re: [PATCH v3] iio: adc: ti-ads7950: add GPIO support

2019-02-20 Thread Justin Chen
On Wed, Feb 20, 2019 at 9:23 AM Jonathan Cameron  wrote:
>
> On Wed, 20 Feb 2019 10:48:49 -0600
> David Lechner  wrote:
>
> > On 2/20/19 6:00 AM, Jonathan Cameron wrote:
> > > On Wed, 13 Feb 2019 09:10:53 +0100
> > > David Lechner  wrote:
> > >
> > >> On 2/12/19 9:57 PM, justinpo...@gmail.com wrote:
> > >>> From: Justin Chen 
> > >>>
> > >>> The ADS79XX has GPIO pins that can be used. Add support for the GPIO
> > >>> pins using the GPIO chip framework.
> > >>>
> > >>> Signed-off-by: Justin Chen 
> > >>> ---
> > >>
> > >> It will be better to split this up into two patches[1]. One to replace
> > >> all uses of indio_dev->mlock with the new local lock and then another to
> > >> add GPIO support.
> > >>
> > >> How are you using/testing this patch? Do we need device tree bindings?
> > >>
I have a custom board with a SoC that is connected to the ADC with
SPI. You don't need any addition device tree binding. Just whatever is
already necessary for the ti-ads7950 driver.
> > >> It will also help reviewers if you add a note about what you changed in
> > >> each revision of the patch when you resubmit. The usual way to do this
> > >> is something like:
> > >>
> > >>   v3 changes:
> > >>
> > >>   - Fixed unlocking mutex too many times in ti_ads7950_init_gpio()
> > >>
> > >> It also is nice to wait a few days at least before submitting the next
> > >> revision to give people some time to respond.
Will do.
> > >
> > > Agreed with all comments except the endian one.
> > > SPI doesn't define an endianness of data on the wire, so we may need
> > > to convert to match whatever ordering the ti chip expects.
> > > I would expect things to be thoroughly broken if we remove those
> > > conversions - particularly as I doubt this is being tested with a
> > > big endian host!
> > >
> > > Jonathan
> >
> > I'm a bit confused then. I got this idea from include/linux/spi.h, which
> > says:
> >
> >   * In-memory data values are always in native CPU byte order, translated
> >   * from the wire byte order (big-endian except with SPI_LSB_FIRST).  So
> >   * for example when bits_per_word is sixteen, buffers are 2N bytes long
> >   * (@len = 2N) and hold N sixteen bit words in CPU byte order.
> >
> >
> > And in the most recent patches to the ti-ads7950 driver where we switched
> > from 8-bit words to 16-bit words, I had to remove the calls to cpu_to_be16()
> > to keep things working.
> Ah, my apologies, I didn't look at this closely enough.
>
> I was assuming we weren't in 16 bit mode here - oops.
>
> Otherwise this wouldn't have any hope of working... Except I'm assuming it 
> is...
> hohum.
>
> Hmm. Given the result of that cpu_to_be16 will be to swap (as almost certainly
> on le system), I'm going to hazzard a guess that the ti device is expecting
> little endian and we should be setting SPI_LSB_FIRST.
> Which is odd because the data sheet definitely looks MSB first. Not to mention
> this isn't be done elsewhere in the driver.
>
> So only option I can fall back on is that it is being used on a be system
> (hence noop) or is a forward port of an older patch for the driver that missed
> your 16 bit change...
>
Yes sorry! This was my mistake. I was juggling two different kernel
versions and one of them didn't have those changes.

Thanks for the review, will address the comments and submit a v4:)

Justin

> >
> > I realize that I am only using one SPI controller, so I may be making a bad
> > assumption here, but it seems to me that it is up to the SPI controller to
> > make sure the bits get sent over the wire in the correct order and we
> > shouldn't have to worry about it here. We are implicitly telling the SPI
> > controller that we need big-endian over the wire by omitting the 
> > SPI_LSB_FIRST
> > flag here:
> >
> >   spi->bits_per_word = 16;
> >   spi->mode |= SPI_CS_WORD;
> >   ret = spi_setup(spi);
> >
> You are entirely correct, I was too lazy and had forgotten your change to
> move to 16 bits.
>
> Jonathan
>


Re: [PATCH] iio: adc: ti-ads7950: add GPIO support

2019-02-11 Thread Justin Chen
On Mon, Feb 11, 2019 at 12:06 PM Jonathan Cameron  wrote:
>
> On Sat, 9 Feb 2019 12:56:11 -0600
> David Lechner  wrote:
>
> > On 2/9/19 11:00 AM, Jonathan Cameron wrote:
> > > Nope.  This is a state lock used to protect against transitions between
> > > different modes of the IIO device (buffered vs polled), it
> > > isn't suitable for general use.
> > >
> > > The driver should be modified to handle that correctly.
> > > We have iio_claim_direct_mode etc that deal with the case
> > > where a device can't do certain operations whilst in buffered
> > > mode.  Note it can fail and should.
> > >
> > > Seems there are more drivers still doing this than I thought.
> > > If anyone is bored and wants to clean them out, that would be
> > > most appreciated!
> > >
> > > If you need locking to protect a local buffer or the device
> > > state, define a new lock to do it with clearly documented
> > > scope.
> >
> > Just as a reminder, there is a use case for this particular
> > chip that requires buffered mode and direct mode at the same
> > time.
> >
> > https://patchwork.kernel.org/patch/10539021/
> > https://patchwork.kernel.org/patch/10527757/
>
> Thanks, I had indeed forgotten that entirely.
> So it should have a local lock and not take mlock explicitly at all.
>
Thanks for all the feedback.
So If I am understanding this correctly. I should create a local lock
to synchronize three different type of transactions (buffered, direct,
gpio).
I do not want to use iio_claim_direct_mode because that doesn't allow
simultaneous use of buffered mode and direct mode, which is necessary
for this driver because of the above mentioned patch.

Justin
> Jonathan


Re: [PATCH v2] iio: adc: ti-ads7950: inconsistency with spi msg

2019-01-30 Thread Justin Chen
On Sat, Jan 26, 2019 at 10:30 AM Jonathan Cameron  wrote:
>
> On Fri, 25 Jan 2019 10:20:22 -0800
> justinpo...@gmail.com wrote:
>
> > From: Justin Chen 
> >
> > To read a channel we require 3 cycles to send, process, and receive
> > the data. The transfer buffer for the third transaction is left blank.
> > This leaves it up to the SPI driver to decide what to do.
> Interesting.  I think that means you may have a bug in your SPI driver.
> The pointer in question is always left set to NULL in the adc
> driver (not explicitly but it will be because ultimately comes from
> a kzalloc).
>
> Documentation for an SPI message makes it clear that NULL is
> allowed.  From include/linux/spi/spi.h
>
> "* Those segments always read the same number of bits as they
>  * write; but one or the other is easily ignored by passing a null buffer
>  * pointer. "
>
> Hmm. It does say 'ignored'.  My assumption has always been that
> means it would be filled with zeros, but maybe I'm wrong.
>
> Mark?
>
I looked more into this and other SPI drivers do fill it with zeros.
I'll submit a patch for the SPI driver instead and see what the SPI
maintainers say.

Thanks,
Justin
> >
> > In one particular case, if the tx buffer is not set the spi driver
> > sets it to 0xff. This puts the ADC in a alarm programming state,
> > therefore the following read to a channel becomes erroneous.
> >
> > Instead of leaving us to the mercy of the SPI driver, we send the
> > ADC cmd on the third transaction to prevent inconsistent behavior.
> >
> > Fixes: 902c4b2446d4 ("iio: adc: New driver for TI ADS7950 chips")
> > Signed-off-by: Justin Chen 
> > ---
> >  drivers/iio/adc/ti-ads7950.c | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c
> > index 0ad6359..1255d8b 100644
> > --- a/drivers/iio/adc/ti-ads7950.c
> > +++ b/drivers/iio/adc/ti-ads7950.c
> > @@ -422,6 +422,7 @@ static int ti_ads7950_probe(struct spi_device *spi)
> >   st->scan_single_xfer[1].tx_buf = >single_tx;
> >   st->scan_single_xfer[1].len = 2;
> >   st->scan_single_xfer[1].cs_change = 1;
> > + st->scan_single_xfer[2].tx_buf = >single_tx;
> >   st->scan_single_xfer[2].rx_buf = >single_rx;
> >   st->scan_single_xfer[2].len = 2;
> >
>


Re: [PATCH] iio: adc: ti-ads7950: inconsistency with spi msg

2019-01-24 Thread Justin Chen
Hello Florian


On Thu, Jan 24, 2019 at 8:30 PM Florian Fainelli  wrote:
>
>
> Hi Justin,
>
> On 1/24/19 5:56 PM, justinpo...@gmail.com wrote:
> > From: Justin Chen 
> >
> > To read a channel we require 3 cycles to send, process, and receive
> > the data. The transfer buffer for the third transaction is left blank.
> > This leaves it up to the SPI driver to decide what to do.
> >
> > In one particular case, if the tx buffer is not set the spi driver
> > sets it to 0xff. This puts the ADC in a alarm programming state,
> > therefore the following read to a channel becomes erroneous.
> >
> > Instead of leaving us to the mercy of the SPI driver, we send the
> > ADC cmd on the third transaction to prevent inconsistent behavior.
>
> Do you think this warrants a Fixes: tag?
>
This was an issue when the driver was introduced. Should I tag that
commit the introduced the driver?
> >
> > Signed-off-by: Justin Chen 
> > ---
> >  drivers/iio/adc/ti-ads7950.c | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c
> > index 0ad6359..5453e10 100644
> > --- a/drivers/iio/adc/ti-ads7950.c
> > +++ b/drivers/iio/adc/ti-ads7950.c
> > @@ -422,6 +422,7 @@ static int ti_ads7950_probe(struct spi_device *spi)
> >   st->scan_single_xfer[1].tx_buf = >single_tx;
> >   st->scan_single_xfer[1].len = 2;
> >   st->scan_single_xfer[1].cs_change = 1;
> > + st->scan_single_xfer[2].rx_buf = >single_tx;
>
> Should this be st->scan_single_xfer[2].tx_buf?
>
Oh yes. Good catch. Careless mistake! v2 incoming.
> >   st->scan_single_xfer[2].rx_buf = >single_rx;
> >   st->scan_single_xfer[2].len = 2;
> >
> >
>
> --
> Florian


[PATCH v2] rtc: brcmstb-waketimer: Set wktmr prescaler

2018-02-26 Thread Justin Chen
The HW default is one tick per second, however instead of assuming this,
lets make sure the waketimer is actually one tick per second before
arming the alarm.

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
Signed-off-by: Justin Chen <justinpo...@gmail.com>
---
 drivers/rtc/rtc-brcmstb-waketimer.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c 
b/drivers/rtc/rtc-brcmstb-waketimer.c
index 796ac79..231b2f7 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -60,6 +60,9 @@ static void brcmstb_waketmr_set_alarm(struct brcmstb_waketmr 
*timer,
 {
brcmstb_waketmr_clear_alarm(timer);
 
+   /* Make sure we are actually counting in seconds */
+   writel_relaxed(timer->rate, timer->base + BRCMSTB_WKTMR_PRESCALER);
+
writel_relaxed(secs + 1, timer->base + BRCMSTB_WKTMR_ALARM);
 }
 
-- 
2.7.4



[PATCH v2] rtc: brcmstb-waketimer: Set wktmr prescaler

2018-02-26 Thread Justin Chen
The HW default is one tick per second, however instead of assuming this,
lets make sure the waketimer is actually one tick per second before
arming the alarm.

Reviewed-by: Florian Fainelli 
Signed-off-by: Justin Chen 
---
 drivers/rtc/rtc-brcmstb-waketimer.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c 
b/drivers/rtc/rtc-brcmstb-waketimer.c
index 796ac79..231b2f7 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -60,6 +60,9 @@ static void brcmstb_waketmr_set_alarm(struct brcmstb_waketmr 
*timer,
 {
brcmstb_waketmr_clear_alarm(timer);
 
+   /* Make sure we are actually counting in seconds */
+   writel_relaxed(timer->rate, timer->base + BRCMSTB_WKTMR_PRESCALER);
+
writel_relaxed(secs + 1, timer->base + BRCMSTB_WKTMR_ALARM);
 }
 
-- 
2.7.4



[PATCH] rtc: brcmstb-waketimer: Set wktmr prescaler

2018-02-21 Thread Justin Chen
The HW default is one tick per second, however instead of assuming this,
lets make sure the waketimer is actually one tick per second before
arming the alarm.

Signed-off-by: Justin Chen <justinpo...@gmail.com>
---
 drivers/rtc/rtc-brcmstb-waketimer.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c 
b/drivers/rtc/rtc-brcmstb-waketimer.c
index 796ac79..46116b7 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -60,6 +60,10 @@ static void brcmstb_waketmr_set_alarm(struct brcmstb_waketmr 
*timer,
 {
brcmstb_waketmr_clear_alarm(timer);
 
+   /* Make sure we are actually counting in seconds */
+   writel_relaxed(BRCMSTB_WKTMR_DEFAULT_FREQ,
+   timer->base + BRCMSTB_WKTMR_PRESCALER);
+
writel_relaxed(secs + 1, timer->base + BRCMSTB_WKTMR_ALARM);
 }
 
-- 
2.7.4



[PATCH] rtc: brcmstb-waketimer: Set wktmr prescaler

2018-02-21 Thread Justin Chen
The HW default is one tick per second, however instead of assuming this,
lets make sure the waketimer is actually one tick per second before
arming the alarm.

Signed-off-by: Justin Chen 
---
 drivers/rtc/rtc-brcmstb-waketimer.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c 
b/drivers/rtc/rtc-brcmstb-waketimer.c
index 796ac79..46116b7 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -60,6 +60,10 @@ static void brcmstb_waketmr_set_alarm(struct brcmstb_waketmr 
*timer,
 {
brcmstb_waketmr_clear_alarm(timer);
 
+   /* Make sure we are actually counting in seconds */
+   writel_relaxed(BRCMSTB_WKTMR_DEFAULT_FREQ,
+   timer->base + BRCMSTB_WKTMR_PRESCALER);
+
writel_relaxed(secs + 1, timer->base + BRCMSTB_WKTMR_ALARM);
 }
 
-- 
2.7.4



[RFC] Potential deadlock with PM and vmstat

2016-11-03 Thread Justin Chen
Hello,

I am experiencing a deadlock in my system when looping through the PM
sequence. The system locks up when trying to bring nonboot cpus down
(hot plugging cpus) with vmstat enabled. The issue is the
cpu_hotplug.lock.

In kernel/cpu.c:_cpu_down(), we begin the cpu bring down. The deadlock
occurs when parking kthreads. This will lock up if the kthread we are
trying to park is waiting on the cpu_hotplug.lock, because this lock
is currently held by the boot cpu at cpu_hotplug_begin().

Here is the sequence that I am seeing(4.1 kernel):
CPU0 goes into the suspend sequence and drops into kernel/cpu.c:_cpu_down().
CPU0 calls cpu_hotplug_begin() and grabs the cpu_hotplug.lock.
CPU0 blocks at smpboot_park_threads(...) waiting for kthreads to be stopped.

CPU1 has a kthread started by vmstat at mm/vmstat.c:
vmstat_shepherd(). In get_online_cpus() the kthread tries to grab the
cpu_hotplug.lock and blocks. So the kthread cannot be parked.

If I am understanding this correctly, this deadlock may happen if
kthreads are parked with the cpu_hotplug.lock held. I haven't tested
this on the most recent kernel(4.9-rc3), but it seems like the
conditions for the deadlock still exist except called in a different
sequence.

If this seems like a valid issue, I will try to put together a patch
to address this issue. Suggestions welcome!

Thanks,
Justin


[RFC] Potential deadlock with PM and vmstat

2016-11-03 Thread Justin Chen
Hello,

I am experiencing a deadlock in my system when looping through the PM
sequence. The system locks up when trying to bring nonboot cpus down
(hot plugging cpus) with vmstat enabled. The issue is the
cpu_hotplug.lock.

In kernel/cpu.c:_cpu_down(), we begin the cpu bring down. The deadlock
occurs when parking kthreads. This will lock up if the kthread we are
trying to park is waiting on the cpu_hotplug.lock, because this lock
is currently held by the boot cpu at cpu_hotplug_begin().

Here is the sequence that I am seeing(4.1 kernel):
CPU0 goes into the suspend sequence and drops into kernel/cpu.c:_cpu_down().
CPU0 calls cpu_hotplug_begin() and grabs the cpu_hotplug.lock.
CPU0 blocks at smpboot_park_threads(...) waiting for kthreads to be stopped.

CPU1 has a kthread started by vmstat at mm/vmstat.c:
vmstat_shepherd(). In get_online_cpus() the kthread tries to grab the
cpu_hotplug.lock and blocks. So the kthread cannot be parked.

If I am understanding this correctly, this deadlock may happen if
kthreads are parked with the cpu_hotplug.lock held. I haven't tested
this on the most recent kernel(4.9-rc3), but it seems like the
conditions for the deadlock still exist except called in a different
sequence.

If this seems like a valid issue, I will try to put together a patch
to address this issue. Suggestions welcome!

Thanks,
Justin


[PATCH v3] bsp: add SoC driver to brcmstb

2016-03-23 Thread Justin Chen
From: Justin Chen <justin.c...@broadcom.com>

Value of soc_dev_attributes:
family = chip family id
soc_id = product id
revision = product revision

Signed-off-by: Justin Chen <justin.c...@broadcom.com>
---
 arch/arm/mach-bcm/Kconfig|1 +
 drivers/soc/brcmstb/common.c |   58 ++
 2 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 7ef1214..b95ea11 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -179,6 +179,7 @@ config ARCH_BRCMSTB
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_WANT_OPTIONAL_GPIOLIB
select SOC_BRCMSTB
+   select SOC_BUS
help
  Say Y if you intend to run the kernel on a Broadcom ARM-based STB
  chipset.
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
index c262c02..daf86ac 100644
--- a/drivers/soc/brcmstb/common.c
+++ b/drivers/soc/brcmstb/common.c
@@ -12,10 +12,18 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 
+static u32 family_id;
+static u32 product_id;
+
 static const struct of_device_id brcmstb_machine_match[] = {
{ .compatible = "brcm,brcmstb", },
{ }
@@ -31,3 +39,53 @@ bool soc_is_brcmstb(void)
 
return of_match_node(brcmstb_machine_match, root) != NULL;
 }
+
+static const struct of_device_id sun_top_ctrl_match[] = {
+   { .compatible = "brcm,brcmstb-sun-top-ctrl", },
+   { }
+};
+
+static int __init brcmstb_soc_device_init(void)
+{
+   struct soc_device_attribute *soc_dev_attr;
+   struct soc_device *soc_dev;
+   struct device_node *sun_top_ctrl;
+   void __iomem *sun_top_ctrl_base;
+
+   sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
+   if (!sun_top_ctrl)
+   return -ENODEV;
+
+   sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
+   if (!sun_top_ctrl_base)
+   return -ENODEV;
+
+   family_id = readl(sun_top_ctrl_base);
+   product_id = readl(sun_top_ctrl_base + 0x4);
+
+   soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+   if (!soc_dev_attr)
+   return -ENOMEM;
+
+   soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
+family_id >> 28 ?
+family_id >> 16 : family_id >> 8);
+   soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
+product_id >> 28 ?
+product_id >> 16 : product_id >> 8);
+   soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
+((product_id & 0xf0) >> 4) + 'A',
+  product_id & 0xf);
+
+   soc_dev = soc_device_register(soc_dev_attr);
+   if (IS_ERR(soc_dev)) {
+   kfree(soc_dev_attr->family);
+   kfree(soc_dev_attr->soc_id);
+   kfree(soc_dev_attr->revision);
+   kfree(soc_dev_attr);
+   return -ENODEV;
+   }
+
+   return 0;
+}
+arch_initcall(brcmstb_soc_device_init);
-- 
1.7.1



[PATCH v3] bsp: add SoC driver to brcmstb

2016-03-23 Thread Justin Chen
From: Justin Chen 

Value of soc_dev_attributes:
family = chip family id
soc_id = product id
revision = product revision

Signed-off-by: Justin Chen 
---
 arch/arm/mach-bcm/Kconfig|1 +
 drivers/soc/brcmstb/common.c |   58 ++
 2 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 7ef1214..b95ea11 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -179,6 +179,7 @@ config ARCH_BRCMSTB
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_WANT_OPTIONAL_GPIOLIB
select SOC_BRCMSTB
+   select SOC_BUS
help
  Say Y if you intend to run the kernel on a Broadcom ARM-based STB
  chipset.
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
index c262c02..daf86ac 100644
--- a/drivers/soc/brcmstb/common.c
+++ b/drivers/soc/brcmstb/common.c
@@ -12,10 +12,18 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 
+static u32 family_id;
+static u32 product_id;
+
 static const struct of_device_id brcmstb_machine_match[] = {
{ .compatible = "brcm,brcmstb", },
{ }
@@ -31,3 +39,53 @@ bool soc_is_brcmstb(void)
 
return of_match_node(brcmstb_machine_match, root) != NULL;
 }
+
+static const struct of_device_id sun_top_ctrl_match[] = {
+   { .compatible = "brcm,brcmstb-sun-top-ctrl", },
+   { }
+};
+
+static int __init brcmstb_soc_device_init(void)
+{
+   struct soc_device_attribute *soc_dev_attr;
+   struct soc_device *soc_dev;
+   struct device_node *sun_top_ctrl;
+   void __iomem *sun_top_ctrl_base;
+
+   sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
+   if (!sun_top_ctrl)
+   return -ENODEV;
+
+   sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
+   if (!sun_top_ctrl_base)
+   return -ENODEV;
+
+   family_id = readl(sun_top_ctrl_base);
+   product_id = readl(sun_top_ctrl_base + 0x4);
+
+   soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+   if (!soc_dev_attr)
+   return -ENOMEM;
+
+   soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
+family_id >> 28 ?
+family_id >> 16 : family_id >> 8);
+   soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
+product_id >> 28 ?
+product_id >> 16 : product_id >> 8);
+   soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
+((product_id & 0xf0) >> 4) + 'A',
+  product_id & 0xf);
+
+   soc_dev = soc_device_register(soc_dev_attr);
+   if (IS_ERR(soc_dev)) {
+   kfree(soc_dev_attr->family);
+   kfree(soc_dev_attr->soc_id);
+   kfree(soc_dev_attr->revision);
+   kfree(soc_dev_attr);
+   return -ENODEV;
+   }
+
+   return 0;
+}
+arch_initcall(brcmstb_soc_device_init);
-- 
1.7.1



[PATCH v2] bsp: add SoC driver to brcmstb

2016-03-11 Thread Justin Chen
From: Justin Chen <justin.c...@broadcom.com>

Value of soc_dev_attributes:
family = chip family id
soc_id = product id
revision = product revision

Signed-off-by: Justin Chen <justin.c...@broadcom.com>
---
 arch/arm/mach-bcm/Kconfig|1 +
 drivers/soc/brcmstb/common.c |   58 ++
 2 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 7ef1214..b95ea11 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -179,6 +179,7 @@ config ARCH_BRCMSTB
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_WANT_OPTIONAL_GPIOLIB
select SOC_BRCMSTB
+   select SOC_BUS
help
  Say Y if you intend to run the kernel on a Broadcom ARM-based STB
  chipset.
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
index c262c02..dc394c0 100644
--- a/drivers/soc/brcmstb/common.c
+++ b/drivers/soc/brcmstb/common.c
@@ -12,10 +12,18 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 
+static u32 family_id;
+static u32 product_id;
+
 static const struct of_device_id brcmstb_machine_match[] = {
{ .compatible = "brcm,brcmstb", },
{ }
@@ -31,3 +39,53 @@ bool soc_is_brcmstb(void)
 
return of_match_node(brcmstb_machine_match, root) != NULL;
 }
+
+static const struct of_device_id sun_top_ctrl_match[] = {
+   { .compatible = "brcm,brcmstb-sun-top-ctrl", },
+   { }
+};
+
+static int __init brcmstb_soc_device_init(void)
+{
+   struct soc_device_attribute *soc_dev_attr;
+   struct soc_device *soc_dev;
+   struct device_node *sun_top_ctrl;
+   void __iomem *sun_top_ctrl_base;
+
+   sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
+   if (!sun_top_ctrl)
+   return -ENODEV;
+
+   sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
+   if (!sun_top_ctrl_base)
+   return -ENODEV;
+
+   family_id = readl(sun_top_ctrl_base);
+   product_id = readl(sun_top_ctrl_base + 0x4);
+
+   soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+   if (!soc_dev_attr)
+   return -ENOMEM;
+
+   soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
+   family_id >> 28 ?
+   family_id >> 16 : family_id >> 8);
+   soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
+   product_id >> 28 ?
+   product_id >> 16 : product_id >> 8);
+   soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
+   (char)(((product_id & 0xff) >> 4) + 65),
+product_id & 0xf);
+
+   soc_dev = soc_device_register(soc_dev_attr);
+   if (IS_ERR(soc_dev)) {
+   kfree(soc_dev_attr->family);
+   kfree(soc_dev_attr->soc_id);
+   kfree(soc_dev_attr->revision);
+   kfree(soc_dev_attr);
+   return -1;
+   }
+
+   return 0;
+}
+arch_initcall(brcmstb_soc_device_init);
-- 
1.7.1



[PATCH v2] bsp: add SoC driver to brcmstb

2016-03-11 Thread Justin Chen
From: Justin Chen 

Value of soc_dev_attributes:
family = chip family id
soc_id = product id
revision = product revision

Signed-off-by: Justin Chen 
---
 arch/arm/mach-bcm/Kconfig|1 +
 drivers/soc/brcmstb/common.c |   58 ++
 2 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 7ef1214..b95ea11 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -179,6 +179,7 @@ config ARCH_BRCMSTB
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_WANT_OPTIONAL_GPIOLIB
select SOC_BRCMSTB
+   select SOC_BUS
help
  Say Y if you intend to run the kernel on a Broadcom ARM-based STB
  chipset.
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
index c262c02..dc394c0 100644
--- a/drivers/soc/brcmstb/common.c
+++ b/drivers/soc/brcmstb/common.c
@@ -12,10 +12,18 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 
+static u32 family_id;
+static u32 product_id;
+
 static const struct of_device_id brcmstb_machine_match[] = {
{ .compatible = "brcm,brcmstb", },
{ }
@@ -31,3 +39,53 @@ bool soc_is_brcmstb(void)
 
return of_match_node(brcmstb_machine_match, root) != NULL;
 }
+
+static const struct of_device_id sun_top_ctrl_match[] = {
+   { .compatible = "brcm,brcmstb-sun-top-ctrl", },
+   { }
+};
+
+static int __init brcmstb_soc_device_init(void)
+{
+   struct soc_device_attribute *soc_dev_attr;
+   struct soc_device *soc_dev;
+   struct device_node *sun_top_ctrl;
+   void __iomem *sun_top_ctrl_base;
+
+   sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
+   if (!sun_top_ctrl)
+   return -ENODEV;
+
+   sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
+   if (!sun_top_ctrl_base)
+   return -ENODEV;
+
+   family_id = readl(sun_top_ctrl_base);
+   product_id = readl(sun_top_ctrl_base + 0x4);
+
+   soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+   if (!soc_dev_attr)
+   return -ENOMEM;
+
+   soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
+   family_id >> 28 ?
+   family_id >> 16 : family_id >> 8);
+   soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
+   product_id >> 28 ?
+   product_id >> 16 : product_id >> 8);
+   soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
+   (char)(((product_id & 0xff) >> 4) + 65),
+product_id & 0xf);
+
+   soc_dev = soc_device_register(soc_dev_attr);
+   if (IS_ERR(soc_dev)) {
+   kfree(soc_dev_attr->family);
+   kfree(soc_dev_attr->soc_id);
+   kfree(soc_dev_attr->revision);
+   kfree(soc_dev_attr);
+   return -1;
+   }
+
+   return 0;
+}
+arch_initcall(brcmstb_soc_device_init);
-- 
1.7.1



[PATCH v2] bsp: add SoC driver to brcmstb

2016-03-04 Thread Justin Chen
From: Justin Chen <justin.c...@broadcom.com>

Value of soc_dev_attributes:
family = chip family id
soc_id = product id
revision = product revision

Signed-off-by: Justin Chen <justin.c...@broadcom.com>
---
 arch/arm/mach-bcm/Kconfig|1 +
 drivers/soc/brcmstb/common.c |   58 ++
 2 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 7ef1214..b95ea11 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -179,6 +179,7 @@ config ARCH_BRCMSTB
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_WANT_OPTIONAL_GPIOLIB
select SOC_BRCMSTB
+   select SOC_BUS
help
  Say Y if you intend to run the kernel on a Broadcom ARM-based STB
  chipset.
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
index c262c02..dc394c0 100644
--- a/drivers/soc/brcmstb/common.c
+++ b/drivers/soc/brcmstb/common.c
@@ -12,10 +12,18 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 
+static u32 family_id;
+static u32 product_id;
+
 static const struct of_device_id brcmstb_machine_match[] = {
{ .compatible = "brcm,brcmstb", },
{ }
@@ -31,3 +39,53 @@ bool soc_is_brcmstb(void)
 
return of_match_node(brcmstb_machine_match, root) != NULL;
 }
+
+static const struct of_device_id sun_top_ctrl_match[] = {
+   { .compatible = "brcm,brcmstb-sun-top-ctrl", },
+   { }
+};
+
+static int __init brcmstb_soc_device_init(void)
+{
+   struct soc_device_attribute *soc_dev_attr;
+   struct soc_device *soc_dev;
+   struct device_node *sun_top_ctrl;
+   void __iomem *sun_top_ctrl_base;
+
+   sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
+   if (!sun_top_ctrl)
+   return -ENODEV;
+
+   sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
+   if (!sun_top_ctrl_base)
+   return -ENODEV;
+
+   family_id = readl(sun_top_ctrl_base);
+   product_id = readl(sun_top_ctrl_base + 0x4);
+
+   soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+   if (!soc_dev_attr)
+   return -ENOMEM;
+
+   soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
+   family_id >> 28 ?
+   family_id >> 16 : family_id >> 8);
+   soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
+   product_id >> 28 ?
+   product_id >> 16 : product_id >> 8);
+   soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
+   (char)(((product_id & 0xff) >> 4) + 65),
+product_id & 0xf);
+
+   soc_dev = soc_device_register(soc_dev_attr);
+   if (IS_ERR(soc_dev)) {
+   kfree(soc_dev_attr->family);
+   kfree(soc_dev_attr->soc_id);
+   kfree(soc_dev_attr->revision);
+   kfree(soc_dev_attr);
+   return -1;
+   }
+
+   return 0;
+}
+arch_initcall(brcmstb_soc_device_init);
-- 
1.7.1



[PATCH v2] bsp: add SoC driver to brcmstb

2016-03-04 Thread Justin Chen
From: Justin Chen 

Value of soc_dev_attributes:
family = chip family id
soc_id = product id
revision = product revision

Signed-off-by: Justin Chen 
---
 arch/arm/mach-bcm/Kconfig|1 +
 drivers/soc/brcmstb/common.c |   58 ++
 2 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 7ef1214..b95ea11 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -179,6 +179,7 @@ config ARCH_BRCMSTB
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_WANT_OPTIONAL_GPIOLIB
select SOC_BRCMSTB
+   select SOC_BUS
help
  Say Y if you intend to run the kernel on a Broadcom ARM-based STB
  chipset.
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
index c262c02..dc394c0 100644
--- a/drivers/soc/brcmstb/common.c
+++ b/drivers/soc/brcmstb/common.c
@@ -12,10 +12,18 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 
+static u32 family_id;
+static u32 product_id;
+
 static const struct of_device_id brcmstb_machine_match[] = {
{ .compatible = "brcm,brcmstb", },
{ }
@@ -31,3 +39,53 @@ bool soc_is_brcmstb(void)
 
return of_match_node(brcmstb_machine_match, root) != NULL;
 }
+
+static const struct of_device_id sun_top_ctrl_match[] = {
+   { .compatible = "brcm,brcmstb-sun-top-ctrl", },
+   { }
+};
+
+static int __init brcmstb_soc_device_init(void)
+{
+   struct soc_device_attribute *soc_dev_attr;
+   struct soc_device *soc_dev;
+   struct device_node *sun_top_ctrl;
+   void __iomem *sun_top_ctrl_base;
+
+   sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
+   if (!sun_top_ctrl)
+   return -ENODEV;
+
+   sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
+   if (!sun_top_ctrl_base)
+   return -ENODEV;
+
+   family_id = readl(sun_top_ctrl_base);
+   product_id = readl(sun_top_ctrl_base + 0x4);
+
+   soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+   if (!soc_dev_attr)
+   return -ENOMEM;
+
+   soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
+   family_id >> 28 ?
+   family_id >> 16 : family_id >> 8);
+   soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
+   product_id >> 28 ?
+   product_id >> 16 : product_id >> 8);
+   soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
+   (char)(((product_id & 0xff) >> 4) + 65),
+product_id & 0xf);
+
+   soc_dev = soc_device_register(soc_dev_attr);
+   if (IS_ERR(soc_dev)) {
+   kfree(soc_dev_attr->family);
+   kfree(soc_dev_attr->soc_id);
+   kfree(soc_dev_attr->revision);
+   kfree(soc_dev_attr);
+   return -1;
+   }
+
+   return 0;
+}
+arch_initcall(brcmstb_soc_device_init);
-- 
1.7.1



[PATCH] bsp: add SoC device to brcmstb

2016-02-25 Thread Justin Chen
From: Justin Chen <justin.c...@broadcom.com>

Added SoC driver at drivers/soc/brcmstb/common.c. Added two
helper functions for getting family/product ID located at
include/linux/soc/brcmstb/brcmstb.h.

Assigned the values of soc_dev_attribute accordingly:
family = chip family id
soc_id = product id
revision = product revision

Signed-off-by: Justin Chen <justin.c...@broadcom.com>
---
 arch/arm/mach-bcm/Kconfig   |1 +
 drivers/soc/brcmstb/common.c|   68 +++
 include/linux/soc/brcmstb/brcmstb.h |7 
 3 files changed, 76 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 7ef1214..b95ea11 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -179,6 +179,7 @@ config ARCH_BRCMSTB
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_WANT_OPTIONAL_GPIOLIB
select SOC_BRCMSTB
+   select SOC_BUS
help
  Say Y if you intend to run the kernel on a Broadcom ARM-based STB
  chipset.
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
index c262c02..dd8cb42 100644
--- a/drivers/soc/brcmstb/common.c
+++ b/drivers/soc/brcmstb/common.c
@@ -12,10 +12,18 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 
+static u32 family_id;
+static u32 product_id;
+
 static const struct of_device_id brcmstb_machine_match[] = {
{ .compatible = "brcm,brcmstb", },
{ }
@@ -31,3 +39,63 @@ bool soc_is_brcmstb(void)
 
return of_match_node(brcmstb_machine_match, root) != NULL;
 }
+
+u32 brcmstb_get_family_id(void)
+{
+   return family_id;
+}
+
+u32 brcmstb_get_product_id(void)
+{
+   return product_id;
+}
+
+static const struct of_device_id sun_top_ctrl_match[] = {
+   { .compatible = "brcm,brcmstb-sun-top-ctrl", },
+   { }
+};
+
+static int __init brcmstb_soc_device_init(void)
+{
+   struct soc_device_attribute *soc_dev_attr;
+   struct soc_device *soc_dev;
+   struct device_node *sun_top_ctrl;
+   void __iomem *sun_top_ctrl_base;
+
+   sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
+   if (!sun_top_ctrl)
+   return -ENODEV;
+
+   sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
+   if (!sun_top_ctrl_base)
+   return -ENODEV;
+
+   family_id = readl(sun_top_ctrl_base);
+   product_id = readl(sun_top_ctrl_base + 0x4);
+
+   soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+   if (!soc_dev_attr)
+   return -ENOMEM;
+
+   soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
+   family_id >> 28 ?
+   family_id >> 16 : family_id >> 8);
+   soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
+   product_id >> 28 ?
+   product_id >> 16 : product_id >> 8);
+   soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
+   (char)(((product_id & 0xff) >> 4) + 65),
+product_id & 0xf);
+
+   soc_dev = soc_device_register(soc_dev_attr);
+   if (IS_ERR(soc_dev)) {
+   kfree(soc_dev_attr->family);
+   kfree(soc_dev_attr->soc_id);
+   kfree(soc_dev_attr->revision);
+   kfree(soc_dev_attr);
+   return -1;
+   }
+
+   return 0;
+}
+arch_initcall(brcmstb_soc_device_init);
diff --git a/include/linux/soc/brcmstb/brcmstb.h 
b/include/linux/soc/brcmstb/brcmstb.h
index 337ce41..ac10b0c 100644
--- a/include/linux/soc/brcmstb/brcmstb.h
+++ b/include/linux/soc/brcmstb/brcmstb.h
@@ -7,4 +7,11 @@
  */
 void brcmstb_biuctrl_init(void);
 
+/*
+ * Helper functions for getting family or product id from the
+ * SoC driver.
+ */
+u32 brcmstb_get_family_id(void);
+u32 brcmstb_get_product_id(void);
+
 #endif /* __BRCMSTB_SOC_H */
-- 
1.7.1



[PATCH] bsp: add SoC device to brcmstb

2016-02-25 Thread Justin Chen
From: Justin Chen 

Added SoC driver at drivers/soc/brcmstb/common.c. Added two
helper functions for getting family/product ID located at
include/linux/soc/brcmstb/brcmstb.h.

Assigned the values of soc_dev_attribute accordingly:
family = chip family id
soc_id = product id
revision = product revision

Signed-off-by: Justin Chen 
---
 arch/arm/mach-bcm/Kconfig   |1 +
 drivers/soc/brcmstb/common.c|   68 +++
 include/linux/soc/brcmstb/brcmstb.h |7 
 3 files changed, 76 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 7ef1214..b95ea11 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -179,6 +179,7 @@ config ARCH_BRCMSTB
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_WANT_OPTIONAL_GPIOLIB
select SOC_BRCMSTB
+   select SOC_BUS
help
  Say Y if you intend to run the kernel on a Broadcom ARM-based STB
  chipset.
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
index c262c02..dd8cb42 100644
--- a/drivers/soc/brcmstb/common.c
+++ b/drivers/soc/brcmstb/common.c
@@ -12,10 +12,18 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 
+static u32 family_id;
+static u32 product_id;
+
 static const struct of_device_id brcmstb_machine_match[] = {
{ .compatible = "brcm,brcmstb", },
{ }
@@ -31,3 +39,63 @@ bool soc_is_brcmstb(void)
 
return of_match_node(brcmstb_machine_match, root) != NULL;
 }
+
+u32 brcmstb_get_family_id(void)
+{
+   return family_id;
+}
+
+u32 brcmstb_get_product_id(void)
+{
+   return product_id;
+}
+
+static const struct of_device_id sun_top_ctrl_match[] = {
+   { .compatible = "brcm,brcmstb-sun-top-ctrl", },
+   { }
+};
+
+static int __init brcmstb_soc_device_init(void)
+{
+   struct soc_device_attribute *soc_dev_attr;
+   struct soc_device *soc_dev;
+   struct device_node *sun_top_ctrl;
+   void __iomem *sun_top_ctrl_base;
+
+   sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
+   if (!sun_top_ctrl)
+   return -ENODEV;
+
+   sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
+   if (!sun_top_ctrl_base)
+   return -ENODEV;
+
+   family_id = readl(sun_top_ctrl_base);
+   product_id = readl(sun_top_ctrl_base + 0x4);
+
+   soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+   if (!soc_dev_attr)
+   return -ENOMEM;
+
+   soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
+   family_id >> 28 ?
+   family_id >> 16 : family_id >> 8);
+   soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
+   product_id >> 28 ?
+   product_id >> 16 : product_id >> 8);
+   soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
+   (char)(((product_id & 0xff) >> 4) + 65),
+product_id & 0xf);
+
+   soc_dev = soc_device_register(soc_dev_attr);
+   if (IS_ERR(soc_dev)) {
+   kfree(soc_dev_attr->family);
+   kfree(soc_dev_attr->soc_id);
+   kfree(soc_dev_attr->revision);
+   kfree(soc_dev_attr);
+   return -1;
+   }
+
+   return 0;
+}
+arch_initcall(brcmstb_soc_device_init);
diff --git a/include/linux/soc/brcmstb/brcmstb.h 
b/include/linux/soc/brcmstb/brcmstb.h
index 337ce41..ac10b0c 100644
--- a/include/linux/soc/brcmstb/brcmstb.h
+++ b/include/linux/soc/brcmstb/brcmstb.h
@@ -7,4 +7,11 @@
  */
 void brcmstb_biuctrl_init(void);
 
+/*
+ * Helper functions for getting family or product id from the
+ * SoC driver.
+ */
+u32 brcmstb_get_family_id(void);
+u32 brcmstb_get_product_id(void);
+
 #endif /* __BRCMSTB_SOC_H */
-- 
1.7.1



[PATCH 2/2 v3] watchdog: Watchdog driver for Broadcom Set-Top Box

2015-09-08 Thread Justin Chen
Watchdog driver for Broadcom 7038 and newer chips.

Signed-off-by: Justin Chen 
Reviewed-by: Guenter Roeck 
---
 drivers/watchdog/Kconfig   |   8 ++
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 237 +
 3 files changed, 246 insertions(+)
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 55c4b5b..b9b 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1292,6 +1292,14 @@ config BCM_KONA_WDT_DEBUG
 
  If in doubt, say 'N'.
 
+config BCM7038_WDT
+   tristate "BCM7038 Watchdog"
+   select WATCHDOG_CORE
+   help
+Watchdog driver for the built-in hardware in Broadcom 7038 SoCs.
+
+Say 'Y or 'M' here to enable the driver.
+
 config IMGPDC_WDT
tristate "Imagination Technologies PDC Watchdog Timer"
depends on HAS_IOMEM
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 59ea9a1..65d4169 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
 obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
 obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
 obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
+obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c
new file mode 100644
index 000..4245b65
--- /dev/null
+++ b/drivers/watchdog/bcm7038_wdt.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define WDT_START_10xff00
+#define WDT_START_20x00ff
+#define WDT_STOP_1 0xee00
+#define WDT_STOP_2 0x00ee
+
+#define WDT_TIMEOUT_REG0x0
+#define WDT_CMD_REG0x4
+
+#define WDT_MIN_TIMEOUT1 /* seconds */
+#define WDT_DEFAULT_TIMEOUT30 /* seconds */
+#define WDT_DEFAULT_RATE   2700
+
+struct bcm7038_watchdog {
+   void __iomem*base;
+   struct watchdog_device  wdd;
+   u32 rate;
+   struct clk  *clk;
+};
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+
+static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 timeout;
+
+   timeout = wdt->rate * wdog->timeout;
+
+   writel(timeout, wdt->base + WDT_TIMEOUT_REG);
+}
+
+static int bcm7038_wdt_ping(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_START_1, wdt->base + WDT_CMD_REG);
+   writel(WDT_START_2, wdt->base + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_start(struct watchdog_device *wdog)
+{
+   bcm7038_wdt_set_timeout_reg(wdog);
+   bcm7038_wdt_ping(wdog);
+
+   return 0;
+}
+
+static int bcm7038_wdt_stop(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_STOP_1, wdt->base + WDT_CMD_REG);
+   writel(WDT_STOP_2, wdt->base + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_set_timeout(struct watchdog_device *wdog,
+  unsigned int t)
+{
+   /* Can't modify timeout value if watchdog timer is running */
+   bcm7038_wdt_stop(wdog);
+   wdog->timeout = t;
+   bcm7038_wdt_start(wdog);
+
+   return 0;
+}
+
+static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 time_left;
+
+   time_left = readl(wdt->base + WDT_CMD_REG);
+
+   return time_left / wdt->rate;
+}
+
+static struct watchdog_info bcm7038_wdt_info = {
+   .identity   = "Broadcom BCM7038 Watchdog Timer",
+   .options= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+   WDIOF_MAGICCLOSE
+};
+
+static struct watchdog_ops bcm7038_wdt_ops = {
+   .owner  = THIS_MODULE,
+   .start  = bcm7038_wdt_start,
+   .stop   = bcm7038_wdt_stop,
+   .set_timeout= bcm7038_wdt_set_timeout,
+   .get_timeleft   = bcm7038_wdt_get_timeleft

[PATCH 1/2 v3] watchdog: bcm7038: add device tree binding documentation

2015-09-08 Thread Justin Chen
Add device tree binding documentation for the watchdog hardware block
on bcm7038 and newer SoCs.

Signed-off-by: Justin Chen 
Acked-by: Guenter Roeck 
---
 .../devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt 
b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
new file mode 100644
index 000..39e5cf5
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
@@ -0,0 +1,19 @@
+BCM7038 Watchdog timer
+
+Required properties:
+
+- compatible : should be "brcm,bcm7038-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Optional properties:
+
+- clocks: The clock running the watchdog. If no clock is found the
+ driver will default to 2700 HZ.
+
+Example:
+
+watchdog {
+   compatible = "brcm,bcm7038-wdt";
+   clocks = <_fixed>;
+   reg = <0xf040a7e8 0x16>;
+};
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/2 v3 ] watchdog: driver for BCM7038 and newer chips.

2015-09-08 Thread Justin Chen
This driver is for a watchdog block contained in all Broadcom Set-top
Box chips since BCM7038. BCM7038 was made public during the 2004 CES,
and since then, many chips use this watchdog block including some cable
modem chips.

Changes since v2:
Added clk_disable_unprepare if watchdog fails to register.

Changes since v1:
Removed clock-frequency because it brought unnecessary complexity to the
driver.
Renamed a few variables.

Patch 1: watchdog device tree binding documentation

Patch 2: watchdog driver

Justin Chen (2):
  watchdog: bcm7038: add device tree binding documentation
  watchdog: Watchdog driver for Broadcom Set-Top Box

 .../bindings/watchdog/brcm,bcm7038-wdt.txt |  19 ++
 drivers/watchdog/Kconfig   |   8 +
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 237 +
 4 files changed, 265 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2 v3] watchdog: bcm7038: add device tree binding documentation

2015-09-08 Thread Justin Chen
Add device tree binding documentation for the watchdog hardware block
on bcm7038 and newer SoCs.

Signed-off-by: Justin Chen <justinpo...@gmail.com>
Acked-by: Guenter Roeck <li...@roeck-us.net>
---
 .../devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt 
b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
new file mode 100644
index 000..39e5cf5
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
@@ -0,0 +1,19 @@
+BCM7038 Watchdog timer
+
+Required properties:
+
+- compatible : should be "brcm,bcm7038-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Optional properties:
+
+- clocks: The clock running the watchdog. If no clock is found the
+ driver will default to 2700 HZ.
+
+Example:
+
+watchdog {
+   compatible = "brcm,bcm7038-wdt";
+   clocks = <_fixed>;
+   reg = <0xf040a7e8 0x16>;
+};
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/2 v3] watchdog: Watchdog driver for Broadcom Set-Top Box

2015-09-08 Thread Justin Chen
Watchdog driver for Broadcom 7038 and newer chips.

Signed-off-by: Justin Chen <justinpo...@gmail.com>
Reviewed-by: Guenter Roeck <li...@roeck-us.net>
---
 drivers/watchdog/Kconfig   |   8 ++
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 237 +
 3 files changed, 246 insertions(+)
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 55c4b5b..b9b 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1292,6 +1292,14 @@ config BCM_KONA_WDT_DEBUG
 
  If in doubt, say 'N'.
 
+config BCM7038_WDT
+   tristate "BCM7038 Watchdog"
+   select WATCHDOG_CORE
+   help
+Watchdog driver for the built-in hardware in Broadcom 7038 SoCs.
+
+Say 'Y or 'M' here to enable the driver.
+
 config IMGPDC_WDT
tristate "Imagination Technologies PDC Watchdog Timer"
depends on HAS_IOMEM
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 59ea9a1..65d4169 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
 obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
 obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
 obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
+obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c
new file mode 100644
index 000..4245b65
--- /dev/null
+++ b/drivers/watchdog/bcm7038_wdt.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define WDT_START_10xff00
+#define WDT_START_20x00ff
+#define WDT_STOP_1 0xee00
+#define WDT_STOP_2 0x00ee
+
+#define WDT_TIMEOUT_REG0x0
+#define WDT_CMD_REG0x4
+
+#define WDT_MIN_TIMEOUT1 /* seconds */
+#define WDT_DEFAULT_TIMEOUT30 /* seconds */
+#define WDT_DEFAULT_RATE   2700
+
+struct bcm7038_watchdog {
+   void __iomem*base;
+   struct watchdog_device  wdd;
+   u32 rate;
+   struct clk  *clk;
+};
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+
+static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 timeout;
+
+   timeout = wdt->rate * wdog->timeout;
+
+   writel(timeout, wdt->base + WDT_TIMEOUT_REG);
+}
+
+static int bcm7038_wdt_ping(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_START_1, wdt->base + WDT_CMD_REG);
+   writel(WDT_START_2, wdt->base + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_start(struct watchdog_device *wdog)
+{
+   bcm7038_wdt_set_timeout_reg(wdog);
+   bcm7038_wdt_ping(wdog);
+
+   return 0;
+}
+
+static int bcm7038_wdt_stop(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_STOP_1, wdt->base + WDT_CMD_REG);
+   writel(WDT_STOP_2, wdt->base + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_set_timeout(struct watchdog_device *wdog,
+  unsigned int t)
+{
+   /* Can't modify timeout value if watchdog timer is running */
+   bcm7038_wdt_stop(wdog);
+   wdog->timeout = t;
+   bcm7038_wdt_start(wdog);
+
+   return 0;
+}
+
+static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 time_left;
+
+   time_left = readl(wdt->base + WDT_CMD_REG);
+
+   return time_left / wdt->rate;
+}
+
+static struct watchdog_info bcm7038_wdt_info = {
+   .identity   = "Broadcom BCM7038 Watchdog Timer",
+   .options= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+   WDIOF_MAGICCLOSE
+};
+
+static struct watchdog_ops bcm7038_wdt_ops = {
+   .owner  = THIS_MODULE,
+   .start  = bcm7038_wdt_start,
+   .stop   = bcm7038_wdt_stop,
+   .set_timeout= bcm7038_wdt_set_timeou

[PATCH 0/2 v3 ] watchdog: driver for BCM7038 and newer chips.

2015-09-08 Thread Justin Chen
This driver is for a watchdog block contained in all Broadcom Set-top
Box chips since BCM7038. BCM7038 was made public during the 2004 CES,
and since then, many chips use this watchdog block including some cable
modem chips.

Changes since v2:
Added clk_disable_unprepare if watchdog fails to register.

Changes since v1:
Removed clock-frequency because it brought unnecessary complexity to the
driver.
Renamed a few variables.

Patch 1: watchdog device tree binding documentation

Patch 2: watchdog driver

Justin Chen (2):
  watchdog: bcm7038: add device tree binding documentation
  watchdog: Watchdog driver for Broadcom Set-Top Box

 .../bindings/watchdog/brcm,bcm7038-wdt.txt |  19 ++
 drivers/watchdog/Kconfig   |   8 +
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 237 +
 4 files changed, 265 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] watchdog_dev: Use device tree alias for naming watchdogs

2015-09-02 Thread Justin Chen
Currently there is no way to easily differentiate multiple
watchdog devices. The watchdogs are named by the order they
are probed.
1st probed watchdog: /dev/watchdog0
2nd probed watchdog: /dev/watchdog1
...

This change uses the alias of the watchdog device node for
the name of the watchdog.
aliases {
watchdog0 = "/./"
watchdog3 = "//."
watchdog2 = "//."
...
}

This will translate to...
/dev/watchdog0
/dev/watchdog3
/dev/watchdog2

v2
Assign alias number to id in watchdog_core instead of watchdog_dev.
If failed to get id, fallback to original ida_simple_get call.

Signed-off-by: Justin Chen 
---
 drivers/watchdog/watchdog_core.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 1a80594..873f139 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -139,7 +139,7 @@ EXPORT_SYMBOL_GPL(watchdog_init_timeout);
 
 static int __watchdog_register_device(struct watchdog_device *wdd)
 {
-   int ret, id, devno;
+   int ret, id = -1, devno;
 
if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL)
return -EINVAL;
@@ -157,7 +157,18 @@ static int __watchdog_register_device(struct 
watchdog_device *wdd)
 */
 
mutex_init(>lock);
-   id = ida_simple_get(_ida, 0, MAX_DOGS, GFP_KERNEL);
+
+   /* Use alias for watchdog id if possible */
+   if (wdd->parent) {
+   ret = of_alias_get_id(wdd->parent->of_node, "watchdog");
+   if (ret >= 0)
+   id = ida_simple_get(_ida, ret,
+   ret + 1, GFP_KERNEL);
+   }
+
+   if (id < 0)
+   id = ida_simple_get(_ida, 0, MAX_DOGS, GFP_KERNEL);
+
if (id < 0)
return id;
wdd->id = id;
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] watchdog_dev: Use device tree alias for naming watchdogs

2015-09-02 Thread Justin Chen
Currently there is no way to easily differentiate multiple
watchdog devices. The watchdogs are named by the order they
are probed.
1st probed watchdog: /dev/watchdog0
2nd probed watchdog: /dev/watchdog1
...

This change uses the alias of the watchdog device node for
the name of the watchdog.
aliases {
watchdog0 = "/./"
watchdog3 = "//."
watchdog2 = "//."
...
}

This will translate to...
/dev/watchdog0
/dev/watchdog3
/dev/watchdog2

v2
Assign alias number to id in watchdog_core instead of watchdog_dev.
If failed to get id, fallback to original ida_simple_get call.

Signed-off-by: Justin Chen <justinpo...@gmail.com>
---
 drivers/watchdog/watchdog_core.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 1a80594..873f139 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -139,7 +139,7 @@ EXPORT_SYMBOL_GPL(watchdog_init_timeout);
 
 static int __watchdog_register_device(struct watchdog_device *wdd)
 {
-   int ret, id, devno;
+   int ret, id = -1, devno;
 
if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL)
return -EINVAL;
@@ -157,7 +157,18 @@ static int __watchdog_register_device(struct 
watchdog_device *wdd)
 */
 
mutex_init(>lock);
-   id = ida_simple_get(_ida, 0, MAX_DOGS, GFP_KERNEL);
+
+   /* Use alias for watchdog id if possible */
+   if (wdd->parent) {
+   ret = of_alias_get_id(wdd->parent->of_node, "watchdog");
+   if (ret >= 0)
+   id = ida_simple_get(_ida, ret,
+   ret + 1, GFP_KERNEL);
+   }
+
+   if (id < 0)
+   id = ida_simple_get(_ida, 0, MAX_DOGS, GFP_KERNEL);
+
if (id < 0)
return id;
wdd->id = id;
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3 0/2] watchdog: driver for BCM7038 and newer chips.

2015-08-31 Thread Justin Chen
This driver is for a watchdog block contained in all Broadcom Set-top
Box chips since BCM7038. BCM7038 was made public during the 2004 CES,
and since then, many chips use this watchdog block including some cable
modem chips.

Changes since v2:
Added clk_disable_unprepare if watchdog fails to register.

Changes since v1:
Removed clock-frequency because it brought unnecessary complexity to the
driver.
Renamed a few variables.

Patch 1: watchdog device tree binding documentation

Patch 2: watchdog driver

Justin Chen (2):
  watchdog: bcm7038: add device tree binding documentation
  watchdog: Watchdog driver for Broadcom Set-Top Box

 .../bindings/watchdog/brcm,bcm7038-wdt.txt |  19 ++
 drivers/watchdog/Kconfig   |   8 +
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 237 +
 4 files changed, 265 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3 1/2] watchdog: bcm7038: add device tree binding documentation

2015-08-31 Thread Justin Chen
Add device tree binding documentation for the watchdog hardware block
on bcm7038 and newer SoCs.

Signed-off-by: Justin Chen 
Acked-by: Guenter Roeck 
---
 .../devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt 
b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
new file mode 100644
index 000..39e5cf5
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
@@ -0,0 +1,19 @@
+BCM7038 Watchdog timer
+
+Required properties:
+
+- compatible : should be "brcm,bcm7038-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Optional properties:
+
+- clocks: The clock running the watchdog. If no clock is found the
+ driver will default to 2700 HZ.
+
+Example:
+
+watchdog {
+   compatible = "brcm,bcm7038-wdt";
+   clocks = <_fixed>;
+   reg = <0xf040a7e8 0x16>;
+};
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3 2/2] watchdog: Watchdog driver for Broadcom Set-Top Box

2015-08-31 Thread Justin Chen
Watchdog driver for Broadcom 7038 and newer chips.

Signed-off-by: Justin Chen 
---
 drivers/watchdog/Kconfig   |   8 ++
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 237 +
 3 files changed, 246 insertions(+)
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 241fafd..4fbe8ab 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1291,6 +1291,14 @@ config BCM_KONA_WDT_DEBUG
 
  If in doubt, say 'N'.
 
+config BCM7038_WDT
+   tristate "BCM7038 Watchdog"
+   select WATCHDOG_CORE
+   help
+Watchdog driver for the built-in hardware in Broadcom 7038 SoCs.
+
+Say 'Y or 'M' here to enable the driver.
+
 config IMGPDC_WDT
tristate "Imagination Technologies PDC Watchdog Timer"
depends on HAS_IOMEM
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 59ea9a1..65d4169 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
 obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
 obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
 obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
+obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c
new file mode 100644
index 000..4245b65
--- /dev/null
+++ b/drivers/watchdog/bcm7038_wdt.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define WDT_START_10xff00
+#define WDT_START_20x00ff
+#define WDT_STOP_1 0xee00
+#define WDT_STOP_2 0x00ee
+
+#define WDT_TIMEOUT_REG0x0
+#define WDT_CMD_REG0x4
+
+#define WDT_MIN_TIMEOUT1 /* seconds */
+#define WDT_DEFAULT_TIMEOUT30 /* seconds */
+#define WDT_DEFAULT_RATE   2700
+
+struct bcm7038_watchdog {
+   void __iomem*base;
+   struct watchdog_device  wdd;
+   u32 rate;
+   struct clk  *clk;
+};
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+
+static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 timeout;
+
+   timeout = wdt->rate * wdog->timeout;
+
+   writel(timeout, wdt->base + WDT_TIMEOUT_REG);
+}
+
+static int bcm7038_wdt_ping(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_START_1, wdt->base + WDT_CMD_REG);
+   writel(WDT_START_2, wdt->base + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_start(struct watchdog_device *wdog)
+{
+   bcm7038_wdt_set_timeout_reg(wdog);
+   bcm7038_wdt_ping(wdog);
+
+   return 0;
+}
+
+static int bcm7038_wdt_stop(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_STOP_1, wdt->base + WDT_CMD_REG);
+   writel(WDT_STOP_2, wdt->base + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_set_timeout(struct watchdog_device *wdog,
+  unsigned int t)
+{
+   /* Can't modify timeout value if watchdog timer is running */
+   bcm7038_wdt_stop(wdog);
+   wdog->timeout = t;
+   bcm7038_wdt_start(wdog);
+
+   return 0;
+}
+
+static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 time_left;
+
+   time_left = readl(wdt->base + WDT_CMD_REG);
+
+   return time_left / wdt->rate;
+}
+
+static struct watchdog_info bcm7038_wdt_info = {
+   .identity   = "Broadcom BCM7038 Watchdog Timer",
+   .options= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+   WDIOF_MAGICCLOSE
+};
+
+static struct watchdog_ops bcm7038_wdt_ops = {
+   .owner  = THIS_MODULE,
+   .start  = bcm7038_wdt_start,
+   .stop   = bcm7038_wdt_stop,
+   .set_timeout= bcm7038_wdt_set_timeout,
+   .get_timeleft   = bcm7038_wdt_get_timeleft,
+};
+
+static int bcm70

[PATCH v3 2/2] watchdog: Watchdog driver for Broadcom Set-Top Box

2015-08-31 Thread Justin Chen
Watchdog driver for Broadcom 7038 and newer chips.

Signed-off-by: Justin Chen <justinpo...@gmail.com>
---
 drivers/watchdog/Kconfig   |   8 ++
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 237 +
 3 files changed, 246 insertions(+)
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 241fafd..4fbe8ab 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1291,6 +1291,14 @@ config BCM_KONA_WDT_DEBUG
 
  If in doubt, say 'N'.
 
+config BCM7038_WDT
+   tristate "BCM7038 Watchdog"
+   select WATCHDOG_CORE
+   help
+Watchdog driver for the built-in hardware in Broadcom 7038 SoCs.
+
+Say 'Y or 'M' here to enable the driver.
+
 config IMGPDC_WDT
tristate "Imagination Technologies PDC Watchdog Timer"
depends on HAS_IOMEM
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 59ea9a1..65d4169 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
 obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
 obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
 obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
+obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c
new file mode 100644
index 000..4245b65
--- /dev/null
+++ b/drivers/watchdog/bcm7038_wdt.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define WDT_START_10xff00
+#define WDT_START_20x00ff
+#define WDT_STOP_1 0xee00
+#define WDT_STOP_2 0x00ee
+
+#define WDT_TIMEOUT_REG0x0
+#define WDT_CMD_REG0x4
+
+#define WDT_MIN_TIMEOUT1 /* seconds */
+#define WDT_DEFAULT_TIMEOUT30 /* seconds */
+#define WDT_DEFAULT_RATE   2700
+
+struct bcm7038_watchdog {
+   void __iomem*base;
+   struct watchdog_device  wdd;
+   u32 rate;
+   struct clk  *clk;
+};
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+
+static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 timeout;
+
+   timeout = wdt->rate * wdog->timeout;
+
+   writel(timeout, wdt->base + WDT_TIMEOUT_REG);
+}
+
+static int bcm7038_wdt_ping(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_START_1, wdt->base + WDT_CMD_REG);
+   writel(WDT_START_2, wdt->base + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_start(struct watchdog_device *wdog)
+{
+   bcm7038_wdt_set_timeout_reg(wdog);
+   bcm7038_wdt_ping(wdog);
+
+   return 0;
+}
+
+static int bcm7038_wdt_stop(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_STOP_1, wdt->base + WDT_CMD_REG);
+   writel(WDT_STOP_2, wdt->base + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_set_timeout(struct watchdog_device *wdog,
+  unsigned int t)
+{
+   /* Can't modify timeout value if watchdog timer is running */
+   bcm7038_wdt_stop(wdog);
+   wdog->timeout = t;
+   bcm7038_wdt_start(wdog);
+
+   return 0;
+}
+
+static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 time_left;
+
+   time_left = readl(wdt->base + WDT_CMD_REG);
+
+   return time_left / wdt->rate;
+}
+
+static struct watchdog_info bcm7038_wdt_info = {
+   .identity   = "Broadcom BCM7038 Watchdog Timer",
+   .options= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+   WDIOF_MAGICCLOSE
+};
+
+static struct watchdog_ops bcm7038_wdt_ops = {
+   .owner  = THIS_MODULE,
+   .start  = bcm7038_wdt_start,
+   .stop   = bcm7038_wdt_stop,
+   .set_timeout= bcm7038_wdt_set_timeout,
+   .get_timeleft   = bcm7038_wdt_get_timeleft

[PATCH v3 1/2] watchdog: bcm7038: add device tree binding documentation

2015-08-31 Thread Justin Chen
Add device tree binding documentation for the watchdog hardware block
on bcm7038 and newer SoCs.

Signed-off-by: Justin Chen <justinpo...@gmail.com>
Acked-by: Guenter Roeck <li...@roeck-us.net>
---
 .../devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt 
b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
new file mode 100644
index 000..39e5cf5
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
@@ -0,0 +1,19 @@
+BCM7038 Watchdog timer
+
+Required properties:
+
+- compatible : should be "brcm,bcm7038-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Optional properties:
+
+- clocks: The clock running the watchdog. If no clock is found the
+ driver will default to 2700 HZ.
+
+Example:
+
+watchdog {
+   compatible = "brcm,bcm7038-wdt";
+   clocks = <_fixed>;
+   reg = <0xf040a7e8 0x16>;
+};
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3 0/2] watchdog: driver for BCM7038 and newer chips.

2015-08-31 Thread Justin Chen
This driver is for a watchdog block contained in all Broadcom Set-top
Box chips since BCM7038. BCM7038 was made public during the 2004 CES,
and since then, many chips use this watchdog block including some cable
modem chips.

Changes since v2:
Added clk_disable_unprepare if watchdog fails to register.

Changes since v1:
Removed clock-frequency because it brought unnecessary complexity to the
driver.
Renamed a few variables.

Patch 1: watchdog device tree binding documentation

Patch 2: watchdog driver

Justin Chen (2):
  watchdog: bcm7038: add device tree binding documentation
  watchdog: Watchdog driver for Broadcom Set-Top Box

 .../bindings/watchdog/brcm,bcm7038-wdt.txt |  19 ++
 drivers/watchdog/Kconfig   |   8 +
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 237 +
 4 files changed, 265 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] watchdog_dev: Use device tree alias for naming watchdogs

2015-08-28 Thread Justin Chen
Currently there is no way to easily differentiate multiple
watchdog devices. The watchdogs are named by the order they
are probed.
1st probed watchdog: /dev/watchdog0
2nd probed watchdog: /dev/watchdog1
...

This change uses the alias of the watchdog device node for
the name of the watchdog.
aliases {
watchdog0 = "/./"
watchdog3 = "//."
watchdog2 = "//."
...
}

This will translate to...
/dev/watchdog0
/dev/watchdog3
/dev/watchdog2

Signed-off-by: Justin Chen 
---
 drivers/watchdog/watchdog_dev.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 6aaefba..52b1f0b 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -41,6 +41,7 @@
 #include   /* For handling misc devices */
 #include /* For __init/__exit/... */
 #include  /* For copy_to_user/put_user/... */
+#include 
 
 #include "watchdog_core.h"
 
@@ -522,7 +523,13 @@ static struct miscdevice watchdog_miscdev = {
 
 int watchdog_dev_register(struct watchdog_device *watchdog)
 {
-   int err, devno;
+   int err, devno, ret;
+
+   if (watchdog->parent) {
+   ret = of_alias_get_id(watchdog->parent->of_node, "watchdog");
+   if (ret >= 0)
+   watchdog->id = ret;
+   }
 
if (watchdog->id == 0) {
old_wdd = watchdog;
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] watchdog_dev: Use device tree alias for naming watchdogs

2015-08-28 Thread Justin Chen
Currently there is no way to easily differentiate multiple
watchdog devices. The watchdogs are named by the order they
are probed.
1st probed watchdog: /dev/watchdog0
2nd probed watchdog: /dev/watchdog1
...

This change uses the alias of the watchdog device node for
the name of the watchdog.
aliases {
watchdog0 = /./
watchdog3 = //.
watchdog2 = //.
...
}

This will translate to...
/dev/watchdog0
/dev/watchdog3
/dev/watchdog2

Signed-off-by: Justin Chen justinpo...@gmail.com
---
 drivers/watchdog/watchdog_dev.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 6aaefba..52b1f0b 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -41,6 +41,7 @@
 #include linux/miscdevice.h  /* For handling misc devices */
 #include linux/init.h/* For __init/__exit/... */
 #include linux/uaccess.h /* For copy_to_user/put_user/... */
+#include linux/of.h
 
 #include watchdog_core.h
 
@@ -522,7 +523,13 @@ static struct miscdevice watchdog_miscdev = {
 
 int watchdog_dev_register(struct watchdog_device *watchdog)
 {
-   int err, devno;
+   int err, devno, ret;
+
+   if (watchdog-parent) {
+   ret = of_alias_get_id(watchdog-parent-of_node, watchdog);
+   if (ret = 0)
+   watchdog-id = ret;
+   }
 
if (watchdog-id == 0) {
old_wdd = watchdog;
-- 
2.1.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 2/2] watchdog: Watchdog driver for Broadcom Set-Top Box

2015-08-27 Thread Justin Chen
Watchdog driver for Broadcom 7038 and newer chips.

Signed-off-by: Justin Chen 
---
 drivers/watchdog/Kconfig   |   8 ++
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 235 +
 3 files changed, 244 insertions(+)
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 241fafd..4fbe8ab 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1291,6 +1291,14 @@ config BCM_KONA_WDT_DEBUG
 
  If in doubt, say 'N'.
 
+config BCM7038_WDT
+   tristate "BCM7038 Watchdog"
+   select WATCHDOG_CORE
+   help
+Watchdog driver for the built-in hardware in Broadcom 7038 SoCs.
+
+Say 'Y or 'M' here to enable the driver.
+
 config IMGPDC_WDT
tristate "Imagination Technologies PDC Watchdog Timer"
depends on HAS_IOMEM
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 59ea9a1..65d4169 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
 obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
 obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
 obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
+obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c
new file mode 100644
index 000..5e54c1b
--- /dev/null
+++ b/drivers/watchdog/bcm7038_wdt.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define WDT_START_10xff00
+#define WDT_START_20x00ff
+#define WDT_STOP_1 0xee00
+#define WDT_STOP_2 0x00ee
+
+#define WDT_TIMEOUT_REG0x0
+#define WDT_CMD_REG0x4
+
+#define WDT_MIN_TIMEOUT1 /* seconds */
+#define WDT_DEFAULT_TIMEOUT30 /* seconds */
+#define WDT_DEFAULT_RATE   2700
+
+struct bcm7038_watchdog {
+   void __iomem*base;
+   struct watchdog_device  wdd;
+   u32 rate;
+   struct clk  *clk;
+};
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+
+static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 timeout;
+
+   timeout = wdt->rate * wdog->timeout;
+
+   writel(timeout, wdt->base + WDT_TIMEOUT_REG);
+}
+
+static int bcm7038_wdt_ping(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_START_1, wdt->base + WDT_CMD_REG);
+   writel(WDT_START_2, wdt->base + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_start(struct watchdog_device *wdog)
+{
+   bcm7038_wdt_set_timeout_reg(wdog);
+   bcm7038_wdt_ping(wdog);
+
+   return 0;
+}
+
+static int bcm7038_wdt_stop(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_STOP_1, wdt->base + WDT_CMD_REG);
+   writel(WDT_STOP_2, wdt->base + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_set_timeout(struct watchdog_device *wdog,
+  unsigned int t)
+{
+   /* Can't modify timeout value if watchdog timer is running */
+   bcm7038_wdt_stop(wdog);
+   wdog->timeout = t;
+   bcm7038_wdt_start(wdog);
+
+   return 0;
+}
+
+static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 time_left;
+
+   time_left = readl(wdt->base + WDT_CMD_REG);
+
+   return time_left / wdt->rate;
+}
+
+static struct watchdog_info bcm7038_wdt_info = {
+   .identity   = "Broadcom BCM7038 Watchdog Timer",
+   .options= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+   WDIOF_MAGICCLOSE
+};
+
+static struct watchdog_ops bcm7038_wdt_ops = {
+   .owner  = THIS_MODULE,
+   .start  = bcm7038_wdt_start,
+   .stop   = bcm7038_wdt_stop,
+   .set_timeout= bcm7038_wdt_set_timeout,
+   .get_timeleft   = bcm7038_wdt_get_timeleft,
+};
+
+static int bcm70

[PATCH v2 0/2] watchdog: driver for BCM7038 and newer chips.

2015-08-27 Thread Justin Chen
This driver is for a watchdog block contained in all Broadcom Set-top
Box chips since BCM7038. BCM7038 was made public during the 2004 CES,
and since then, many chips use this watchdog block including some cable
modem chips.

Changes since v1:
Removed clock-frequency because it brought unnecessary complexity to the
driver.
Renamed a few variables.

Patch 1: watchdog device tree binding documentation

Patch 2: watchdog driver

Justin Chen (2):
  watchdog: bcm7038: add device tree binding documentation
  watchdog: Watchdog driver for Broadcom Set-Top Box

 .../bindings/watchdog/brcm,bcm7038-wdt.txt |  19 ++
 drivers/watchdog/Kconfig   |   8 +
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 235 +
 4 files changed, 263 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 1/2] watchdog: bcm7038: add device tree binding documentation

2015-08-27 Thread Justin Chen
Add device tree binding documentation for the watchdog hardware block
on bcm7038 and newer SoCs.

Signed-off-by: Justin Chen 
---
 .../devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt 
b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
new file mode 100644
index 000..39e5cf5
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
@@ -0,0 +1,19 @@
+BCM7038 Watchdog timer
+
+Required properties:
+
+- compatible : should be "brcm,bcm7038-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Optional properties:
+
+- clocks: The clock running the watchdog. If no clock is found the
+ driver will default to 2700 HZ.
+
+Example:
+
+watchdog {
+   compatible = "brcm,bcm7038-wdt";
+   clocks = <_fixed>;
+   reg = <0xf040a7e8 0x16>;
+};
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 0/2] watchdog: driver for BCM7038 and newer chips.

2015-08-27 Thread Justin Chen
This driver is for a watchdog block contained in all Broadcom Set-top
Box chips since BCM7038. BCM7038 was made public during the 2004 CES,
and since then, many chips use this watchdog block including some cable
modem chips.

Changes since v1:
Removed clock-frequency because it brought unnecessary complexity to the
driver.
Renamed a few variables.

Patch 1: watchdog device tree binding documentation

Patch 2: watchdog driver

Justin Chen (2):
  watchdog: bcm7038: add device tree binding documentation
  watchdog: Watchdog driver for Broadcom Set-Top Box

 .../bindings/watchdog/brcm,bcm7038-wdt.txt |  19 ++
 drivers/watchdog/Kconfig   |   8 +
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 235 +
 4 files changed, 263 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

-- 
2.1.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 1/2] watchdog: bcm7038: add device tree binding documentation

2015-08-27 Thread Justin Chen
Add device tree binding documentation for the watchdog hardware block
on bcm7038 and newer SoCs.

Signed-off-by: Justin Chen justinpo...@gmail.com
---
 .../devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt 
b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
new file mode 100644
index 000..39e5cf5
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
@@ -0,0 +1,19 @@
+BCM7038 Watchdog timer
+
+Required properties:
+
+- compatible : should be brcm,bcm7038-wdt
+- reg : Specifies base physical address and size of the registers.
+
+Optional properties:
+
+- clocks: The clock running the watchdog. If no clock is found the
+ driver will default to 2700 HZ.
+
+Example:
+
+watchdog {
+   compatible = brcm,bcm7038-wdt;
+   clocks = upg_fixed;
+   reg = 0xf040a7e8 0x16;
+};
-- 
2.1.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 2/2] watchdog: Watchdog driver for Broadcom Set-Top Box

2015-08-27 Thread Justin Chen
Watchdog driver for Broadcom 7038 and newer chips.

Signed-off-by: Justin Chen justinpo...@gmail.com
---
 drivers/watchdog/Kconfig   |   8 ++
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 235 +
 3 files changed, 244 insertions(+)
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 241fafd..4fbe8ab 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1291,6 +1291,14 @@ config BCM_KONA_WDT_DEBUG
 
  If in doubt, say 'N'.
 
+config BCM7038_WDT
+   tristate BCM7038 Watchdog
+   select WATCHDOG_CORE
+   help
+Watchdog driver for the built-in hardware in Broadcom 7038 SoCs.
+
+Say 'Y or 'M' here to enable the driver.
+
 config IMGPDC_WDT
tristate Imagination Technologies PDC Watchdog Timer
depends on HAS_IOMEM
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 59ea9a1..65d4169 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
 obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
 obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
 obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
+obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c
new file mode 100644
index 000..5e54c1b
--- /dev/null
+++ b/drivers/watchdog/bcm7038_wdt.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * 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.
+ */
+
+#include linux/clk.h
+#include linux/init.h
+#include linux/io.h
+#include linux/module.h
+#include linux/of.h
+#include linux/platform_device.h
+#include linux/pm.h
+#include linux/watchdog.h
+
+#define WDT_START_10xff00
+#define WDT_START_20x00ff
+#define WDT_STOP_1 0xee00
+#define WDT_STOP_2 0x00ee
+
+#define WDT_TIMEOUT_REG0x0
+#define WDT_CMD_REG0x4
+
+#define WDT_MIN_TIMEOUT1 /* seconds */
+#define WDT_DEFAULT_TIMEOUT30 /* seconds */
+#define WDT_DEFAULT_RATE   2700
+
+struct bcm7038_watchdog {
+   void __iomem*base;
+   struct watchdog_device  wdd;
+   u32 rate;
+   struct clk  *clk;
+};
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+
+static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 timeout;
+
+   timeout = wdt-rate * wdog-timeout;
+
+   writel(timeout, wdt-base + WDT_TIMEOUT_REG);
+}
+
+static int bcm7038_wdt_ping(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_START_1, wdt-base + WDT_CMD_REG);
+   writel(WDT_START_2, wdt-base + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_start(struct watchdog_device *wdog)
+{
+   bcm7038_wdt_set_timeout_reg(wdog);
+   bcm7038_wdt_ping(wdog);
+
+   return 0;
+}
+
+static int bcm7038_wdt_stop(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_STOP_1, wdt-base + WDT_CMD_REG);
+   writel(WDT_STOP_2, wdt-base + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_set_timeout(struct watchdog_device *wdog,
+  unsigned int t)
+{
+   /* Can't modify timeout value if watchdog timer is running */
+   bcm7038_wdt_stop(wdog);
+   wdog-timeout = t;
+   bcm7038_wdt_start(wdog);
+
+   return 0;
+}
+
+static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 time_left;
+
+   time_left = readl(wdt-base + WDT_CMD_REG);
+
+   return time_left / wdt-rate;
+}
+
+static struct watchdog_info bcm7038_wdt_info = {
+   .identity   = Broadcom BCM7038 Watchdog Timer,
+   .options= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+   WDIOF_MAGICCLOSE
+};
+
+static struct watchdog_ops bcm7038_wdt_ops = {
+   .owner  = THIS_MODULE,
+   .start  = bcm7038_wdt_start,
+   .stop   = bcm7038_wdt_stop,
+   .set_timeout= bcm7038_wdt_set_timeout,
+   .get_timeleft

Re: [PATCH 1/2] watchdog: bcm7038: add device tree binding documentation

2015-08-25 Thread Justin Chen
On Tue, Aug 25, 2015 at 12:04:48PM -0700, Guenter Roeck wrote:
> Justin,
> 
> On Tue, Aug 25, 2015 at 10:55:40AM -0700, Justin Chen wrote:
> > 
> > Hello Guenter,
> > 
> > > Is 'clock-frequency' really needed (and useful), or would it make more 
> > > sense
> > > to expect the user to configure a fixed clock if nothing else is 
> > > available ?
> > > How do other drivers handle this ?
> > 
> > The reason for 'clock-frequency' was for a case where our device tree did 
> > not
> > have clocks. Creating a new fixed clock for a single device seems 
> > unnecessary
> > compared to a 'clock-frequency' property. Their is a use for 
> > 'clock-frequency',
> > but it is not really necessary. However, this is my first linux patch, so I 
> > do 
> > not fully trust my judgement on this...
> > 
> 
> All that is needed for a fixed clock is a devicetree entry for it. Not sure
> I understand your line of argument; you add a lot of complexity and code
> just to avoid those few lines in the dts file (especially with 500+
> "fixed-clock" nodes in other devicetree files).
> 
> Thanks,
> Guenter

Ok your argument makes sense. I will remove the clock-frequency property and 
modify the driver accordingly. Thank you for your feedback!

Thanks,
Justin
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] watchdog: bcm7038: add device tree binding documentation

2015-08-25 Thread Justin Chen
On Sun, Aug 23, 2015 at 08:32:21PM -0700, Guenter Roeck wrote:
> Hi Justin,
> 
> On 08/20/2015 10:41 AM, Justin Chen wrote:
> >Add device tree binding docmentation for the watchdog hardware block
> >on bcm7038 and newer SoCs.
> >
> >Signed-off-by: Justin Chen 
> >---
> >  .../devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt | 19 
> > +++
> >  1 file changed, 19 insertions(+)
> >  create mode 100644 
> > Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
> >
> >diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt 
> >b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
> >new file mode 100644
> >index 000..adb8260
> >--- /dev/null
> >+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
> >@@ -0,0 +1,19 @@
> >+BCM7038 Watchdog timer
> >+
> >+Required properties:
> >+
> >+- compatible : should be "brcm,bcm7038-wdt"
> >+- reg : Specifies base physical address and size of the registers.
> >+
> >+Optional properties:
> >+
> >+- clocks: the clock running the watchdog
> >+- clock-frequency: the rate of the clock
> 
> Is 'clock-frequency' really needed (and useful), or would it make more sense
> to expect the user to configure a fixed clock if nothing else is available ?
> How do other drivers handle this ?
> 
> Thanks,
> Guenter
> 
> >+
> >+Example:
> >+
> >+watchdog {
> >+compatible = "brcm,bcm7038-wdt";
> >+clocks = <_fixed>;
> >+reg = <0xf040a7e8 0x16>;
> >+};
> >
>

Hello Guenter,

> Is 'clock-frequency' really needed (and useful), or would it make more sense
> to expect the user to configure a fixed clock if nothing else is available ?
> How do other drivers handle this ?

The reason for 'clock-frequency' was for a case where our device tree did not
have clocks. Creating a new fixed clock for a single device seems unnecessary
compared to a 'clock-frequency' property. Their is a use for 'clock-frequency',
but it is not really necessary. However, this is my first linux patch, so I do 
not fully trust my judgement on this...

Looking at other drivers, none of them have both clock and clock-frequency.

Thank you for your time on reviewing the patch Guenter. Much appreciated!

Thanks,
Justin Chen
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] watchdog: bcm7038: add device tree binding documentation

2015-08-25 Thread Justin Chen
On Sun, Aug 23, 2015 at 08:32:21PM -0700, Guenter Roeck wrote:
 Hi Justin,
 
 On 08/20/2015 10:41 AM, Justin Chen wrote:
 Add device tree binding docmentation for the watchdog hardware block
 on bcm7038 and newer SoCs.
 
 Signed-off-by: Justin Chen justinpo...@gmail.com
 ---
   .../devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt | 19 
  +++
   1 file changed, 19 insertions(+)
   create mode 100644 
  Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
 
 diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt 
 b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
 new file mode 100644
 index 000..adb8260
 --- /dev/null
 +++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
 @@ -0,0 +1,19 @@
 +BCM7038 Watchdog timer
 +
 +Required properties:
 +
 +- compatible : should be brcm,bcm7038-wdt
 +- reg : Specifies base physical address and size of the registers.
 +
 +Optional properties:
 +
 +- clocks: the clock running the watchdog
 +- clock-frequency: the rate of the clock
 
 Is 'clock-frequency' really needed (and useful), or would it make more sense
 to expect the user to configure a fixed clock if nothing else is available ?
 How do other drivers handle this ?
 
 Thanks,
 Guenter
 
 +
 +Example:
 +
 +watchdog {
 +compatible = brcm,bcm7038-wdt;
 +clocks = upg_fixed;
 +reg = 0xf040a7e8 0x16;
 +};
 


Hello Guenter,

 Is 'clock-frequency' really needed (and useful), or would it make more sense
 to expect the user to configure a fixed clock if nothing else is available ?
 How do other drivers handle this ?

The reason for 'clock-frequency' was for a case where our device tree did not
have clocks. Creating a new fixed clock for a single device seems unnecessary
compared to a 'clock-frequency' property. Their is a use for 'clock-frequency',
but it is not really necessary. However, this is my first linux patch, so I do 
not fully trust my judgement on this...

Looking at other drivers, none of them have both clock and clock-frequency.

Thank you for your time on reviewing the patch Guenter. Much appreciated!

Thanks,
Justin Chen
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] watchdog: bcm7038: add device tree binding documentation

2015-08-25 Thread Justin Chen
On Tue, Aug 25, 2015 at 12:04:48PM -0700, Guenter Roeck wrote:
 Justin,
 
 On Tue, Aug 25, 2015 at 10:55:40AM -0700, Justin Chen wrote:
  
  Hello Guenter,
  
   Is 'clock-frequency' really needed (and useful), or would it make more 
   sense
   to expect the user to configure a fixed clock if nothing else is 
   available ?
   How do other drivers handle this ?
  
  The reason for 'clock-frequency' was for a case where our device tree did 
  not
  have clocks. Creating a new fixed clock for a single device seems 
  unnecessary
  compared to a 'clock-frequency' property. Their is a use for 
  'clock-frequency',
  but it is not really necessary. However, this is my first linux patch, so I 
  do 
  not fully trust my judgement on this...
  
 
 All that is needed for a fixed clock is a devicetree entry for it. Not sure
 I understand your line of argument; you add a lot of complexity and code
 just to avoid those few lines in the dts file (especially with 500+
 fixed-clock nodes in other devicetree files).
 
 Thanks,
 Guenter

Ok your argument makes sense. I will remove the clock-frequency property and 
modify the driver accordingly. Thank you for your feedback!

Thanks,
Justin
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/2] watchdog: Watchdog driver for Broadcom Set-Top Box

2015-08-20 Thread Justin Chen
Watchdog driver for Broadcom 7038 and newer chips.

Signed-off-by: Justin Chen 
---
 drivers/watchdog/Kconfig   |   8 ++
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 253 +
 3 files changed, 262 insertions(+)
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 241fafd..4fbe8ab 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1291,6 +1291,14 @@ config BCM_KONA_WDT_DEBUG
 
  If in doubt, say 'N'.
 
+config BCM7038_WDT
+   tristate "BCM7038 Watchdog"
+   select WATCHDOG_CORE
+   help
+Watchdog driver for the built-in hardware in Broadcom 7038 SoCs.
+
+Say 'Y or 'M' here to enable the driver.
+
 config IMGPDC_WDT
tristate "Imagination Technologies PDC Watchdog Timer"
depends on HAS_IOMEM
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 59ea9a1..65d4169 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
 obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
 obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
 obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
+obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c
new file mode 100644
index 000..a70730b
--- /dev/null
+++ b/drivers/watchdog/bcm7038_wdt.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define WDT_START_10xff00
+#define WDT_START_20x00ff
+#define WDT_STOP_1 0xee00
+#define WDT_STOP_2 0x00ee
+
+#define WDT_TIMEOUT_REG0x0
+#define WDT_CMD_REG0x4
+
+#define WDT_MIN_TIMEOUT1 /* seconds */
+#define WDT_DEFAULT_TIMEOUT30 /* seconds */
+#define WDT_DEFAULT_RATE   2700
+
+struct bcm7038_watchdog {
+   void __iomem*reg;
+   struct clk  *wdt_clk;
+   struct watchdog_device  wdd;
+   u32 hz;
+};
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+
+static unsigned long bcm7038_wdt_get_rate(struct bcm7038_watchdog *wdt)
+{
+   /* if clock is missing return hz */
+   if (!wdt->wdt_clk)
+   return wdt->hz;
+
+   return clk_get_rate(wdt->wdt_clk);
+
+}
+
+static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 timeout;
+
+   timeout = bcm7038_wdt_get_rate(wdt) * wdog->timeout;
+
+   writel(timeout, wdt->reg + WDT_TIMEOUT_REG);
+}
+
+static int bcm7038_wdt_ping(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_START_1, wdt->reg + WDT_CMD_REG);
+   writel(WDT_START_2, wdt->reg + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_start(struct watchdog_device *wdog)
+{
+   bcm7038_wdt_set_timeout_reg(wdog);
+   bcm7038_wdt_ping(wdog);
+
+   return 0;
+}
+
+static int bcm7038_wdt_stop(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_STOP_1, wdt->reg + WDT_CMD_REG);
+   writel(WDT_STOP_2, wdt->reg + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_set_timeout(struct watchdog_device *wdog,
+   unsigned int t)
+{
+   if (watchdog_timeout_invalid(wdog, t))
+   return -EINVAL;
+
+   /* Can't modify timeout value if watchdog timer is running */
+   bcm7038_wdt_stop(wdog);
+   wdog->timeout = t;
+   bcm7038_wdt_start(wdog);
+
+   return 0;
+}
+
+static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 time_left;
+
+   time_left = readl(wdt->reg + WDT_CMD_REG);
+
+   return time_left / bcm7038_wdt_get_rate(wdt);
+}
+
+static struct watchdog_info bcm7038_wdt_info = {
+   .identity   = "Broadcom Watchdog Timer",
+   .options= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+  

[PATCH 1/2] watchdog: bcm7038: add device tree binding documentation

2015-08-20 Thread Justin Chen
Add device tree binding docmentation for the watchdog hardware block
on bcm7038 and newer SoCs.

Signed-off-by: Justin Chen 
---
 .../devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt 
b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
new file mode 100644
index 000..adb8260
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
@@ -0,0 +1,19 @@
+BCM7038 Watchdog timer
+
+Required properties:
+
+- compatible : should be "brcm,bcm7038-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Optional properties:
+
+- clocks: the clock running the watchdog
+- clock-frequency: the rate of the clock
+
+Example:
+
+watchdog {
+   compatible = "brcm,bcm7038-wdt";
+   clocks = <_fixed>;
+   reg = <0xf040a7e8 0x16>;
+};
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/2] watchdog: driver for BCM7038 and newer chips.

2015-08-20 Thread Justin Chen
This driver is for a watchdog block contained in all Broadcom Set-top
Box chips since BCM7038. BCM7038 was made public during the 2004 CES,
and since then, many chips use this watchdog block including some cable
modem chips.

Patch 1: watchdog device tree binding documentation

Patch 2: watchdog driver

Justin Chen (2):
  watchdog: bcm7038: add device tree binding documentation
  watchdog: Watchdog driver for Broadcom Set-Top Box

 .../bindings/watchdog/brcm,bcm7038-wdt.txt |  19 ++
 drivers/watchdog/Kconfig   |   8 +
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 253 +
 4 files changed, 281 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/2] watchdog: Watchdog driver for Broadcom Set-Top Box

2015-08-20 Thread Justin Chen
Watchdog driver for Broadcom 7038 and newer chips.

Signed-off-by: Justin Chen justinpo...@gmail.com
---
 drivers/watchdog/Kconfig   |   8 ++
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 253 +
 3 files changed, 262 insertions(+)
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 241fafd..4fbe8ab 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1291,6 +1291,14 @@ config BCM_KONA_WDT_DEBUG
 
  If in doubt, say 'N'.
 
+config BCM7038_WDT
+   tristate BCM7038 Watchdog
+   select WATCHDOG_CORE
+   help
+Watchdog driver for the built-in hardware in Broadcom 7038 SoCs.
+
+Say 'Y or 'M' here to enable the driver.
+
 config IMGPDC_WDT
tristate Imagination Technologies PDC Watchdog Timer
depends on HAS_IOMEM
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 59ea9a1..65d4169 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
 obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
 obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
 obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
+obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c
new file mode 100644
index 000..a70730b
--- /dev/null
+++ b/drivers/watchdog/bcm7038_wdt.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * 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.
+ */
+
+#include linux/module.h
+#include linux/init.h
+#include linux/io.h
+#include linux/platform_device.h
+#include linux/watchdog.h
+#include linux/clk.h
+#include linux/of.h
+#include linux/pm.h
+
+#define WDT_START_10xff00
+#define WDT_START_20x00ff
+#define WDT_STOP_1 0xee00
+#define WDT_STOP_2 0x00ee
+
+#define WDT_TIMEOUT_REG0x0
+#define WDT_CMD_REG0x4
+
+#define WDT_MIN_TIMEOUT1 /* seconds */
+#define WDT_DEFAULT_TIMEOUT30 /* seconds */
+#define WDT_DEFAULT_RATE   2700
+
+struct bcm7038_watchdog {
+   void __iomem*reg;
+   struct clk  *wdt_clk;
+   struct watchdog_device  wdd;
+   u32 hz;
+};
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+
+static unsigned long bcm7038_wdt_get_rate(struct bcm7038_watchdog *wdt)
+{
+   /* if clock is missing return hz */
+   if (!wdt-wdt_clk)
+   return wdt-hz;
+
+   return clk_get_rate(wdt-wdt_clk);
+
+}
+
+static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 timeout;
+
+   timeout = bcm7038_wdt_get_rate(wdt) * wdog-timeout;
+
+   writel(timeout, wdt-reg + WDT_TIMEOUT_REG);
+}
+
+static int bcm7038_wdt_ping(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_START_1, wdt-reg + WDT_CMD_REG);
+   writel(WDT_START_2, wdt-reg + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_start(struct watchdog_device *wdog)
+{
+   bcm7038_wdt_set_timeout_reg(wdog);
+   bcm7038_wdt_ping(wdog);
+
+   return 0;
+}
+
+static int bcm7038_wdt_stop(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+   writel(WDT_STOP_1, wdt-reg + WDT_CMD_REG);
+   writel(WDT_STOP_2, wdt-reg + WDT_CMD_REG);
+
+   return 0;
+}
+
+static int bcm7038_wdt_set_timeout(struct watchdog_device *wdog,
+   unsigned int t)
+{
+   if (watchdog_timeout_invalid(wdog, t))
+   return -EINVAL;
+
+   /* Can't modify timeout value if watchdog timer is running */
+   bcm7038_wdt_stop(wdog);
+   wdog-timeout = t;
+   bcm7038_wdt_start(wdog);
+
+   return 0;
+}
+
+static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog)
+{
+   struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+   u32 time_left;
+
+   time_left = readl(wdt-reg + WDT_CMD_REG);
+
+   return time_left / bcm7038_wdt_get_rate(wdt);
+}
+
+static struct watchdog_info bcm7038_wdt_info = {
+   .identity   = Broadcom Watchdog Timer,
+   .options= WDIOF_SETTIMEOUT

[PATCH 1/2] watchdog: bcm7038: add device tree binding documentation

2015-08-20 Thread Justin Chen
Add device tree binding docmentation for the watchdog hardware block
on bcm7038 and newer SoCs.

Signed-off-by: Justin Chen justinpo...@gmail.com
---
 .../devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt 
b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
new file mode 100644
index 000..adb8260
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
@@ -0,0 +1,19 @@
+BCM7038 Watchdog timer
+
+Required properties:
+
+- compatible : should be brcm,bcm7038-wdt
+- reg : Specifies base physical address and size of the registers.
+
+Optional properties:
+
+- clocks: the clock running the watchdog
+- clock-frequency: the rate of the clock
+
+Example:
+
+watchdog {
+   compatible = brcm,bcm7038-wdt;
+   clocks = upg_fixed;
+   reg = 0xf040a7e8 0x16;
+};
-- 
2.1.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/2] watchdog: driver for BCM7038 and newer chips.

2015-08-20 Thread Justin Chen
This driver is for a watchdog block contained in all Broadcom Set-top
Box chips since BCM7038. BCM7038 was made public during the 2004 CES,
and since then, many chips use this watchdog block including some cable
modem chips.

Patch 1: watchdog device tree binding documentation

Patch 2: watchdog driver

Justin Chen (2):
  watchdog: bcm7038: add device tree binding documentation
  watchdog: Watchdog driver for Broadcom Set-Top Box

 .../bindings/watchdog/brcm,bcm7038-wdt.txt |  19 ++
 drivers/watchdog/Kconfig   |   8 +
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm7038_wdt.c | 253 +
 4 files changed, 281 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
 create mode 100644 drivers/watchdog/bcm7038_wdt.c

-- 
2.1.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/