s5j/pwm: rework pwm lower-half driver
authorBongryul Lee <bongryul.lee@samsung.com>
Thu, 20 Apr 2017 11:56:46 +0000 (20:56 +0900)
committerHeesub Shin <heesub.shin@samsung.com>
Sat, 6 May 2017 14:00:41 +0000 (23:00 +0900)
This commit rewrites PWM driver in completely new. Every code lines were
reviewed and then any redundant or unnecessary code lines have been
removed. This reduces binary footprints of PWM driver quite a lot as
following:

    Before:
       text    data     bss     dec     hex filename
       1755     160     386    2301     8fd s5j_pwm.o

    After:
       text    data     bss     dec     hex filename
        655      72       0     727     2d7 s5j_pwm.o

Change-Id: If2a4e46e47e4c2d7225abfa8419e1ccf76fb08a9
Signed-off-by: Bongryul Lee <bongryul.lee@samsung.com>
18 files changed:
apps/examples/sensorbd_demo/Kconfig
apps/examples/sensorbd_demo/examples/pwm_buzzer.c
apps/examples/sensorbd_demo/examples/pwm_led.c
build/configs/artik053/extra/defconfig
build/configs/artik053/minimal/defconfig
build/configs/artik053/nettest/defconfig
build/configs/artik053/typical/defconfig
build/configs/sidk_s5jt200/hello/defconfig
build/configs/sidk_s5jt200/hello_with_tash/defconfig
build/configs/sidk_s5jt200/kernel_sample/defconfig
build/configs/sidk_s5jt200/sidk_tash_wlan/defconfig
build/configs/sidk_s5jt200/tc/defconfig
framework/src/iotbus/iotbus_pwm.c
os/arch/arm/src/s5j/Kconfig
os/arch/arm/src/s5j/chip/s5j_memorymap.h
os/arch/arm/src/s5j/chip/s5jt200_pwm.h [new file with mode: 0644]
os/arch/arm/src/s5j/s5j_pwm.c
os/arch/arm/src/s5j/s5j_pwm.h

index 1521a24..dea474c 100644 (file)
@@ -17,7 +17,12 @@ config EXAMPLES_SENSORBOARD
        select I2C_USERIO
        select S5J_I2C
        select PWM
-       select S5J_PWM
+       select S5J_PWM0
+       select S5J_PWM1
+       select S5J_PWM2
+       select S5J_PWM3
+       select S5J_PWM4
+       select S5J_PWM5
        default n
        ---help---
                Enable the Sensor Board Example
index 490bc37..b443881 100644 (file)
@@ -94,7 +94,7 @@ void pwmbuzzer_main(int argc, char *argv[])
 
        for (i = 0; i < 8; i++) {
                pwm_info.frequency = octavef[i];
-               pwm_info.duty = octaved[i];
+               pwm_info.duty = (octaved[i] * 65536) / 100;
                ioctl(fd1, PWMIOC_SETCHARACTERISTICS, (unsigned long)((uintptr_t)&pwm_info));
                ioctl(fd1, PWMIOC_START);
 
@@ -103,7 +103,7 @@ void pwmbuzzer_main(int argc, char *argv[])
 
        for (i = 0; i < 40; i++) {
                pwm_info.frequency = furelisef[i];
-               pwm_info.duty = furelised[i];
+               pwm_info.duty = (furelised[i] * 65536) / 100;
                ioctl(fd2, PWMIOC_SETCHARACTERISTICS, (unsigned long)((uintptr_t)&pwm_info));
                ioctl(fd2, PWMIOC_START);
 
index 3d1cfc3..a49b75c 100644 (file)
@@ -71,13 +71,13 @@ void ledpwm_main(int argc, char *argv[])
        for (i = 0; i < 100; i = i + 3) {
                printf("brightness %d, %d\n", i, 99 - i);
 
-               pwm_info.duty = i;
+               pwm_info.duty = i * 65536 / 100;
                ioctl(fd1, PWMIOC_SETCHARACTERISTICS, (unsigned long)((uintptr_t)&pwm_info));
                ioctl(fd2, PWMIOC_SETCHARACTERISTICS, (unsigned long)((uintptr_t)&pwm_info));
                ioctl(fd1, PWMIOC_START);
                ioctl(fd2, PWMIOC_START);
 
-               pwm_info.duty = 99 - i;
+               pwm_info.duty = (99 - i) * 65536 / 100;
                ioctl(fd3, PWMIOC_SETCHARACTERISTICS, (unsigned long)((uintptr_t)&pwm_info));
                ioctl(fd4, PWMIOC_SETCHARACTERISTICS, (unsigned long)((uintptr_t)&pwm_info));
                ioctl(fd3, PWMIOC_START);
index 44cd9e8..0db35a4 100644 (file)
@@ -151,7 +151,12 @@ CONFIG_S5J_S5JT200=y
 CONFIG_S5J_HAVE_ADC=y
 CONFIG_S5J_HAVE_DMA=y
 CONFIG_S5J_HAVE_I2C=y
-CONFIG_S5J_HAVE_PWM=y
+CONFIG_S5J_HAVE_PWM0=y
+CONFIG_S5J_HAVE_PWM1=y
+CONFIG_S5J_HAVE_PWM2=y
+CONFIG_S5J_HAVE_PWM3=y
+CONFIG_S5J_HAVE_PWM4=y
+CONFIG_S5J_HAVE_PWM5=y
 CONFIG_S5J_HAVE_PWR=y
 CONFIG_S5J_HAVE_RTC=y
 CONFIG_S5J_HAVE_SFLASH=y
@@ -173,6 +178,12 @@ CONFIG_S5J_UART2=y
 CONFIG_S5J_UART3=y
 CONFIG_S5J_UARTDBG=y
 CONFIG_S5J_PWM=y
+CONFIG_S5J_PWM0=y
+CONFIG_S5J_PWM1=y
+CONFIG_S5J_PWM2=y
+CONFIG_S5J_PWM3=y
+CONFIG_S5J_PWM4=y
+CONFIG_S5J_PWM5=y
 CONFIG_S5J_SSS=y
 CONFIG_S5J_SPI=y
 CONFIG_S5J_WATCHDOG=y
index 7735d01..84205cf 100644 (file)
@@ -151,7 +151,12 @@ CONFIG_S5J_S5JT200=y
 CONFIG_S5J_HAVE_ADC=y
 CONFIG_S5J_HAVE_DMA=y
 CONFIG_S5J_HAVE_I2C=y
-CONFIG_S5J_HAVE_PWM=y
+CONFIG_S5J_HAVE_PWM0=y
+CONFIG_S5J_HAVE_PWM1=y
+CONFIG_S5J_HAVE_PWM2=y
+CONFIG_S5J_HAVE_PWM3=y
+CONFIG_S5J_HAVE_PWM4=y
+CONFIG_S5J_HAVE_PWM5=y
 CONFIG_S5J_HAVE_PWR=y
 CONFIG_S5J_HAVE_RTC=y
 CONFIG_S5J_HAVE_SFLASH=y
index 322b1d5..6b3d43d 100644 (file)
@@ -155,12 +155,24 @@ CONFIG_S5J_HAVE_UART0=y
 CONFIG_S5J_HAVE_UART1=y
 CONFIG_S5J_HAVE_UART2=y
 CONFIG_S5J_HAVE_UART3=y
+CONFIG_S5J_HAVE_PWM0=y
+CONFIG_S5J_HAVE_PWM1=y
+CONFIG_S5J_HAVE_PWM2=y
+CONFIG_S5J_HAVE_PWM3=y
+CONFIG_S5J_HAVE_PWM4=y
+CONFIG_S5J_HAVE_PWM5=y
 CONFIG_S5J_UARTDBG=y
 CONFIG_S5J_UART0=y
 CONFIG_S5J_UART1=y
 CONFIG_S5J_UART2=y
 CONFIG_S5J_UART3=y
 CONFIG_S5J_PWM=y
+CONFIG_S5J_PWM0=y
+CONFIG_S5J_PWM1=y
+CONFIG_S5J_PWM2=y
+CONFIG_S5J_PWM3=y
+CONFIG_S5J_PWM4=y
+CONFIG_S5J_PWM5=y
 CONFIG_S5J_SSS=y
 
 #
index f42f753..6784582 100644 (file)
@@ -151,7 +151,12 @@ CONFIG_S5J_S5JT200=y
 CONFIG_S5J_HAVE_ADC=y
 CONFIG_S5J_HAVE_DMA=y
 CONFIG_S5J_HAVE_I2C=y
-CONFIG_S5J_HAVE_PWM=y
+CONFIG_S5J_HAVE_PWM0=y
+CONFIG_S5J_HAVE_PWM1=y
+CONFIG_S5J_HAVE_PWM2=y
+CONFIG_S5J_HAVE_PWM3=y
+CONFIG_S5J_HAVE_PWM4=y
+CONFIG_S5J_HAVE_PWM5=y
 CONFIG_S5J_HAVE_PWR=y
 CONFIG_S5J_HAVE_RTC=y
 CONFIG_S5J_HAVE_SFLASH=y
@@ -173,6 +178,12 @@ CONFIG_S5J_UART2=y
 CONFIG_S5J_UART3=y
 CONFIG_S5J_UARTDBG=y
 CONFIG_S5J_PWM=y
+CONFIG_S5J_PWM0=y
+CONFIG_S5J_PWM1=y
+CONFIG_S5J_PWM2=y
+CONFIG_S5J_PWM3=y
+CONFIG_S5J_PWM4=y
+CONFIG_S5J_PWM5=y
 CONFIG_S5J_SSS=y
 CONFIG_S5J_SPI=y
 CONFIG_S5J_WATCHDOG=y
index 680f2dc..e91a15f 100644 (file)
@@ -113,6 +113,12 @@ CONFIG_S5J_S5JT200=y
 #
 CONFIG_SERIAL_TERMIOS=y
 CONFIG_ARCH_HAVE_SERIAL_TERMIOS=y
+CONFIG_S5J_HAVE_PWM0=y
+CONFIG_S5J_HAVE_PWM1=y
+CONFIG_S5J_HAVE_PWM2=y
+CONFIG_S5J_HAVE_PWM3=y
+CONFIG_S5J_HAVE_PWM4=y
+CONFIG_S5J_HAVE_PWM5=y
 CONFIG_S5J_HAVE_UARTDBG=y
 CONFIG_S5J_HAVE_UART0=y
 CONFIG_S5J_HAVE_UART1=y
index 9392c64..a1f6f0a 100644 (file)
@@ -139,6 +139,12 @@ CONFIG_S5J_S5JT200=y
 #
 CONFIG_SERIAL_TERMIOS=y
 CONFIG_ARCH_HAVE_SERIAL_TERMIOS=y
+CONFIG_S5J_HAVE_PWM0=y
+CONFIG_S5J_HAVE_PWM1=y
+CONFIG_S5J_HAVE_PWM2=y
+CONFIG_S5J_HAVE_PWM3=y
+CONFIG_S5J_HAVE_PWM4=y
+CONFIG_S5J_HAVE_PWM5=y
 CONFIG_S5J_HAVE_UARTDBG=y
 CONFIG_S5J_HAVE_UART0=y
 CONFIG_S5J_HAVE_UART1=y
index 2dd126d..ed75f76 100644 (file)
@@ -139,6 +139,12 @@ CONFIG_S5J_S5JT200=y
 #
 CONFIG_SERIAL_TERMIOS=y
 CONFIG_ARCH_HAVE_SERIAL_TERMIOS=y
+CONFIG_S5J_HAVE_PWM0=y
+CONFIG_S5J_HAVE_PWM1=y
+CONFIG_S5J_HAVE_PWM2=y
+CONFIG_S5J_HAVE_PWM3=y
+CONFIG_S5J_HAVE_PWM4=y
+CONFIG_S5J_HAVE_PWM5=y
 CONFIG_S5J_HAVE_UARTDBG=y
 CONFIG_S5J_HAVE_UART0=y
 CONFIG_S5J_HAVE_UART1=y
index aa9355f..9401400 100644 (file)
@@ -150,6 +150,12 @@ CONFIG_S5J_S5JT200=y
 #
 CONFIG_SERIAL_TERMIOS=y
 CONFIG_ARCH_HAVE_SERIAL_TERMIOS=y
+CONFIG_S5J_HAVE_PWM0=y
+CONFIG_S5J_HAVE_PWM1=y
+CONFIG_S5J_HAVE_PWM2=y
+CONFIG_S5J_HAVE_PWM3=y
+CONFIG_S5J_HAVE_PWM4=y
+CONFIG_S5J_HAVE_PWM5=y
 CONFIG_S5J_HAVE_UARTDBG=y
 CONFIG_S5J_HAVE_UART0=y
 CONFIG_S5J_HAVE_UART1=y
@@ -161,6 +167,12 @@ CONFIG_S5J_UART1=y
 CONFIG_S5J_UART2=y
 CONFIG_S5J_UART3=y
 CONFIG_S5J_PWM=y
+CONFIG_S5J_PWM0=y
+CONFIG_S5J_PWM1=y
+CONFIG_S5J_PWM2=y
+CONFIG_S5J_PWM3=y
+CONFIG_S5J_PWM4=y
+CONFIG_S5J_PWM5=y
 CONFIG_S5J_SSS=y
 
 #
index 52e1f6f..d310356 100644 (file)
@@ -139,6 +139,12 @@ CONFIG_S5J_S5JT200=y
 #
 CONFIG_SERIAL_TERMIOS=y
 CONFIG_ARCH_HAVE_SERIAL_TERMIOS=y
+CONFIG_S5J_HAVE_PWM0=y
+CONFIG_S5J_HAVE_PWM1=y
+CONFIG_S5J_HAVE_PWM2=y
+CONFIG_S5J_HAVE_PWM3=y
+CONFIG_S5J_HAVE_PWM4=y
+CONFIG_S5J_HAVE_PWM5=y
 CONFIG_S5J_HAVE_UARTDBG=y
 CONFIG_S5J_HAVE_UART0=y
 CONFIG_S5J_HAVE_UART1=y
@@ -150,6 +156,12 @@ CONFIG_S5J_UART1=y
 CONFIG_S5J_UART2=y
 CONFIG_S5J_UART3=y
 CONFIG_S5J_PWM=y
+CONFIG_S5J_PWM0=y
+CONFIG_S5J_PWM1=y
+CONFIG_S5J_PWM2=y
+CONFIG_S5J_PWM3=y
+CONFIG_S5J_PWM4=y
+CONFIG_S5J_PWM5=y
 # CONFIG_S5J_SSS is not set
 
 #
index e4a7d4d..248bcfd 100644 (file)
@@ -117,7 +117,7 @@ int iotbus_pwm_set_duty_cycle(iotbus_pwm_context_h pwm, uint32_t duty_cycle)
                return IOTBUS_ERROR_UNKNOWN;
        }
 
-       info->duty = duty_cycle;
+       info->duty = (duty_cycle * 65536) / 100;
        ret = ioctl(fd, PWMIOC_SETCHARACTERISTICS, (unsigned long)((uintptr_t)info));
        if (ret < 0) {
                zdbg("ioctl(PWMIOC_SETCHARACTERISTICS) failed: %d\n", errno);
index bd53a63..b33f778 100644 (file)
@@ -26,7 +26,12 @@ config S5J_S5JT200
        select S5J_HAVE_ADC
        select S5J_HAVE_DMA
        select S5J_HAVE_I2C
-       select S5J_HAVE_PWM
+       select S5J_HAVE_PWM0
+       select S5J_HAVE_PWM1
+       select S5J_HAVE_PWM2
+       select S5J_HAVE_PWM3
+       select S5J_HAVE_PWM4
+       select S5J_HAVE_PWM5
        select S5J_HAVE_PWR
        select S5J_HAVE_RTC
        select S5J_HAVE_SFLASH
@@ -56,7 +61,27 @@ config S5J_HAVE_I2C
        bool
        default n
 
-config S5J_HAVE_PWM
+config S5J_HAVE_PWM0
+       bool
+       default n
+
+config S5J_HAVE_PWM1
+       bool
+       default n
+
+config S5J_HAVE_PWM2
+       bool
+       default n
+
+config S5J_HAVE_PWM3
+       bool
+       default n
+
+config S5J_HAVE_PWM4
+       bool
+       default n
+
+config S5J_HAVE_PWM5
        bool
        default n
 
@@ -171,8 +196,43 @@ config S5J_UARTDBG
        select ARCH_HAVE_SERIAL_TERMIOS
 
 config S5J_PWM
-       bool "PWM"
-       depends on S5J_HAVE_PWM
+       bool
+       default n
+
+config S5J_PWM0
+       bool "PWM0"
+       depends on S5J_HAVE_PWM0
+       select S5J_PWM
+       default n
+
+config S5J_PWM1
+       bool "PWM1"
+       depends on S5J_HAVE_PWM1
+       select S5J_PWM
+       default n
+
+config S5J_PWM2
+       bool "PWM2"
+       depends on S5J_HAVE_PWM2
+       select S5J_PWM
+       default n
+
+config S5J_PWM3
+       bool "PWM3"
+       depends on S5J_HAVE_PWM3
+       select S5J_PWM
+       default n
+
+config S5J_PWM4
+       bool "PWM4"
+       depends on S5J_HAVE_PWM4
+       select S5J_PWM
+       default n
+
+config S5J_PWM5
+       bool "PWM5"
+       depends on S5J_HAVE_PWM5
+       select S5J_PWM
        default n
 
 config S5J_SSS
index f9c481f..cd6d966 100644 (file)
@@ -94,8 +94,8 @@
 #define S5J_GIC_BASE           0x80400000
 #define PMU_BASE                       0x80090000
 #define PMU_ALIVE_BASE         PMU_BASE        /*Temp */
-#define PWM0_BASE                      0x802E0000
-#define PWM1_BASE                      0x802F0000
+#define S5J_PWM0_BASE          0x802E0000
+#define S5J_PWM1_BASE          0x802F0000
 #define S5J_SPI0_BASE          0x80240000
 #define S5J_SPI1_BASE          0x80250000
 #define S5J_SPI2_BASE          0x80260000
diff --git a/os/arch/arm/src/s5j/chip/s5jt200_pwm.h b/os/arch/arm/src/s5j/chip/s5jt200_pwm.h
new file mode 100644 (file)
index 0000000..fca2a2d
--- /dev/null
@@ -0,0 +1,307 @@
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * arch/arm/src/s5j/chip/s5j200_pwm.h
+ *
+ *   Copyright (C) 2009-2010, 2014-2015 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_S5J_CHIP_S5JT200_PWM_H
+#define __ARCH_ARM_SRC_S5J_CHIP_S5JT200_PWM_H
+
+/****************************************************************************
+ * Include
+ ****************************************************************************/
+#include "s5j_memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* PWM Register Offsets *****************************************************/
+#define S5J_PWM_TCFG0_OFFSET           0x00
+#define S5J_PWM_TCFG1_OFFSET           0x04
+#define S5J_PWM_TCON_OFFSET                    0x08
+#define S5J_PWM_TCNTB0_OFFSET          0x0C
+#define S5J_PWM_TCMPB0_OFFSET          0x10
+#define S5J_PWM_TCNTO0_OFFSET          0x14
+#define S5J_PWM_TCNTB1_OFFSET          0x1C
+#define S5J_PWM_TCMPB1_OFFSET          0x20
+#define S5J_PWM_TCNTO1_OFFSET          0x24
+#define S5J_PWM_TCNTB2_OFFSET          0x1C
+#define S5J_PWM_TCMPB2_OFFSET          0x20
+#define S5J_PWM_TCNTO2_OFFSET          0x24
+#define S5J_PWM_TCNTB3_OFFSET          0x2C
+#define S5J_PWM_TCMPB3_OFFSET          0x30
+#define S5J_PWM_TCNTO3_OFFSET          0x34
+#define S5J_PWM_TINT_CSTAT_OFFSET      0x44
+
+#define S5J_PWM_TCNTB_OFFSET(c)                (S5J_PWM_TCNTB0_OFFSET + 0xc * (c))
+#define S5J_PWM_TCMPB_OFFSET(c)                (S5J_PWM_TCMPB0_OFFSET + 0xc * (c))
+#define S5J_PWM_TCNTO_OFFSET(c)                (S5J_PWM_TCNTO0_OFFSET + 0xc * (c))
+
+/* PWM0 Register Address ****************************************************/
+#define S5J_PWM0_TCFG0                 (S5J_PWM0_BASE + S5J_PWM_TCFG0_OFFSET)
+#define S5J_PWM0_TCFG1                 (S5J_PWM0_BASE + S5J_PWM_TCFG1_OFFSET)
+#define S5J_PWM0_TCON                  (S5J_PWM0_BASE + S5J_PWM_TCON_OFFSET)
+#define S5J_PWM0_TCNTB0                        (S5J_PWM0_BASE + S5J_PWM_TCNTB0_OFFSET)
+#define S5J_PWM0_TCMPB0                        (S5J_PWM0_BASE + S5J_PWM_TCMPB0_OFFSET)
+#define S5J_PWM0_TCNTO0                        (S5J_PWM0_BASE + S5J_PWM_TCNTO0_OFFSET)
+#define S5J_PWM0_TCNTB1                        (S5J_PWM0_BASE + S5J_PWM_TCNTB1_OFFSET)
+#define S5J_PWM0_TCMPB1                        (S5J_PWM0_BASE + S5J_PWM_TCMPB1_OFFSET)
+#define S5J_PWM0_TCNTO1                        (S5J_PWM0_BASE + S5J_PWM_TCNTO1_OFFSET)
+#define S5J_PWM0_TCNTB2                        (S5J_PWM0_BASE + S5J_PWM_TCNTB2_OFFSET)
+#define S5J_PWM0_TCMPB2                        (S5J_PWM0_BASE + S5J_PWM_TCMPB2_OFFSET)
+#define S5J_PWM0_TCNTO2                        (S5J_PWM0_BASE + S5J_PWM_TCNTO2_OFFSET)
+#define S5J_PWM0_TCNTB3                        (S5J_PWM0_BASE + S5J_PWM_TCNTB3_OFFSET)
+#define S5J_PWM0_TCMPB3                        (S5J_PWM0_BASE + S5J_PWM_TCMPB3_OFFSET)
+#define S5J_PWM0_TCNTO3                        (S5J_PWM0_BASE + S5J_PWM_TCNTO3_OFFSET)
+#define S5J_PWM0_TINT_CSTAT            (S5J_PWM0_BASE + S5J_PWM_TINT_CSTAT_OFFSET)
+
+/* PWM1 Register Address ****************************************************/
+#define S5J_PWM1_TCFG0                 (S5J_PWM1_BASE + S5J_PWM_TCFG0_OFFSET)
+#define S5J_PWM1_TCFG1                 (S5J_PWM1_BASE + S5J_PWM_TCFG1_OFFSET)
+#define S5J_PWM1_TCON                  (S5J_PWM1_BASE + S5J_PWM_TCON_OFFSET)
+#define S5J_PWM1_TCNTB0                        (S5J_PWM1_BASE + S5J_PWM_TCNTB0_OFFSET)
+#define S5J_PWM1_TCMPB0                        (S5J_PWM1_BASE + S5J_PWM_TCMPB0_OFFSET)
+#define S5J_PWM1_TCNTO0                        (S5J_PWM1_BASE + S5J_PWM_TCNTO0_OFFSET)
+#define S5J_PWM1_TCNTB1                        (S5J_PWM1_BASE + S5J_PWM_TCNTB1_OFFSET)
+#define S5J_PWM1_TCMPB1                        (S5J_PWM1_BASE + S5J_PWM_TCMPB1_OFFSET)
+#define S5J_PWM1_TCNTO1                        (S5J_PWM1_BASE + S5J_PWM_TCNTO1_OFFSET)
+#define S5J_PWM1_TCNTB2                        (S5J_PWM1_BASE + S5J_PWM_TCNTB2_OFFSET)
+#define S5J_PWM1_TCMPB2                        (S5J_PWM1_BASE + S5J_PWM_TCMPB2_OFFSET)
+#define S5J_PWM1_TCNTO2                        (S5J_PWM1_BASE + S5J_PWM_TCNTO2_OFFSET)
+#define S5J_PWM1_TCNTB3                        (S5J_PWM1_BASE + S5J_PWM_TCNTB3_OFFSET)
+#define S5J_PWM1_TCMPB3                        (S5J_PWM1_BASE + S5J_PWM_TCMPB3_OFFSET)
+#define S5J_PWM1_TCNTO3                        (S5J_PWM1_BASE + S5J_PWM_TCNTO3_OFFSET)
+#define S5J_PWM1_TINT_CSTAT            (S5J_PWM1_BASE + S5J_PWM_TINT_CSTAT_OFFSET)
+
+/* Register Bitfield Definitions ********************************************/
+/* TCFG0 ********************************************************************/
+#define PWM_TCFG0_DEADZONE_LENGTH_SHIFT        16
+#define PWM_TCFG0_DEADZONE_LENGTH_MASK (0xff << PWM_TCFG0_DEADZONE_LENGTH_SHIFT)
+
+#define PWM_TCFG0_PRESCALER0_SHIFT             0
+#define PWM_TCFG0_PRESCALER0_MASK              (0xff << PWM_TCFG0_PRESCALER0_SHIFT)
+
+#define PWM_TCFG0_PRESCALER1_SHIFT             8
+#define PWM_TCFG0_PRESCALER1_MASK              (0xff << PWM_TCFG0_PRESCALER1_SHIFT)
+
+/* TCFG1 ********************************************************************/
+#define PWM_TCFG1_DIVIDER_MUX_SHIFT(c) (4 * c)
+#define PWM_TCFG1_DIVIDER_MUX_MASK(c)  (0x7 << PWM_TCFG1_DIVIDER_MUX_SHIFT(c))
+#define PWM_TCFG1_DIVIDER_MUX_DIV1(c)  (0x0 << PWM_TCFG1_DIVIDER_MUX_SHIFT(c))
+#define PWM_TCFG1_DIVIDER_MUX_DIV2(c)  (0x1 << PWM_TCFG1_DIVIDER_MUX_SHIFT(c))
+#define PWM_TCFG1_DIVIDER_MUX_DIV4(c)  (0x2 << PWM_TCFG1_DIVIDER_MUX_SHIFT(c))
+#define PWM_TCFG1_DIVIDER_MUX_DIV8(c)  (0x3 << PWM_TCFG1_DIVIDER_MUX_SHIFT(c))
+#define PWM_TCFG1_DIVIDER_MUX_DIV16(c) (0x4 << PWM_TCFG1_DIVIDER_MUX_SHIFT(c))
+
+#define PWM_TCFG1_DIVIDER_MUX3_SHIFT   PWM_TCFG1_DIVIDER_MUX_SHIFT(3)
+#define PWM_TCFG1_DIVIDER_MUX3_MASK            PWM_TCFG1_DIVIDER_MUX_MASK(3)
+#define PWM_TCFG1_DIVIDER_MUX3_DIV1            PWM_TCFG1_DIVIDER_MUX_DIV1(3)
+#define PWM_TCFG1_DIVIDER_MUX3_DIV2            PWM_TCFG1_DIVIDER_MUX_DIV2(3)
+#define PWM_TCFG1_DIVIDER_MUX3_DIV4            PWM_TCFG1_DIVIDER_MUX_DIV4(3)
+#define PWM_TCFG1_DIVIDER_MUX3_DIV8            PWM_TCFG1_DIVIDER_MUX_DIV8(3)
+#define PWM_TCFG1_DIVIDER_MUX3_DIV16   PWM_TCFG1_DIVIDER_MUX_DIV16(3)
+
+#define PWM_TCFG1_DIVIDER_MUX2_SHIFT   PWM_TCFG1_DIVIDER_MUX_SHIFT(2)
+#define PWM_TCFG1_DIVIDER_MUX2_MASK            PWM_TCFG1_DIVIDER_MUX_MASK(2)
+#define PWM_TCFG1_DIVIDER_MUX2_DIV1            PWM_TCFG1_DIVIDER_MUX_DIV1(2)
+#define PWM_TCFG1_DIVIDER_MUX2_DIV2            PWM_TCFG1_DIVIDER_MUX_DIV2(2)
+#define PWM_TCFG1_DIVIDER_MUX2_DIV4            PWM_TCFG1_DIVIDER_MUX_DIV4(2)
+#define PWM_TCFG1_DIVIDER_MUX2_DIV8            PWM_TCFG1_DIVIDER_MUX_DIV8(2)
+#define PWM_TCFG1_DIVIDER_MUX2_DIV16   PWM_TCFG1_DIVIDER_MUX_DIV16(2)
+
+#define PWM_TCFG1_DIVIDER_MUX1_SHIFT   PWM_TCFG1_DIVIDER_MUX_SHIFT(1)
+#define PWM_TCFG1_DIVIDER_MUX1_MASK            PWM_TCFG1_DIVIDER_MUX_MASK(1)
+#define PWM_TCFG1_DIVIDER_MUX1_DIV1            PWM_TCFG1_DIVIDER_MUX_DIV1(1)
+#define PWM_TCFG1_DIVIDER_MUX1_DIV2            PWM_TCFG1_DIVIDER_MUX_DIV2(1)
+#define PWM_TCFG1_DIVIDER_MUX1_DIV4            PWM_TCFG1_DIVIDER_MUX_DIV4(1)
+#define PWM_TCFG1_DIVIDER_MUX1_DIV8            PWM_TCFG1_DIVIDER_MUX_DIV8(1)
+#define PWM_TCFG1_DIVIDER_MUX1_DIV16   PWM_TCFG1_DIVIDER_MUX_DIV16(1)
+
+#define PWM_TCFG1_DIVIDER_MUX0_SHIFT   PWM_TCFG1_DIVIDER_MUX_SHIFT(0)
+#define PWM_TCFG1_DIVIDER_MUX0_MASK            PWM_TCFG1_DIVIDER_MUX_MASK(0)
+#define PWM_TCFG1_DIVIDER_MUX0_DIV1            PWM_TCFG1_DIVIDER_MUX_DIV1(0)
+#define PWM_TCFG1_DIVIDER_MUX0_DIV2            PWM_TCFG1_DIVIDER_MUX_DIV2(0)
+#define PWM_TCFG1_DIVIDER_MUX0_DIV4            PWM_TCFG1_DIVIDER_MUX_DIV4(0)
+#define PWM_TCFG1_DIVIDER_MUX0_DIV8            PWM_TCFG1_DIVIDER_MUX_DIV8(0)
+#define PWM_TCFG1_DIVIDER_MUX0_DIV16   PWM_TCFG1_DIVIDER_MUX_DIV16(0)
+
+/* TCON *********************************************************************/
+#define PWM_TCON_TIM_BIT_OFFSET(c)                     (((c) == 0 ? 0 : ((c) + 1)) * 4)
+
+#define PWM_TCON_TIM_STARTSTOP_SHIFT(c)                PWM_TCON_TIM_BIT_OFFSET(c)
+#define PWM_TCON_TIM_STARTSTOP_MASK(c)         (0x1 << PWM_TCON_TIM_STARTSTOP_SHIFT(c))
+#define PWM_TCON_TIM_STARTSTOP_STOP(c)         (0x0 << PWM_TCON_TIM_STARTSTOP_SHIFT(c))
+#define PWM_TCON_TIM_STARTSTOP_START(c)                (0x1 << PWM_TCON_TIM_STARTSTOP_SHIFT(c))
+
+#define PWM_TCON_TIM_MAN_UPDATE_SHIFT(c)       (PWM_TCON_TIM_BIT_OFFSET(c) + 1)
+#define PWM_TCON_TIM_MAN_UPDATE_MASK(c)                (0x1 << PWM_TCON_TIM_MAN_UPDATE_SHIFT(c))
+#define PWM_TCON_TIM_MAN_UPDATE_NOP(c)         (0x0 << PWM_TCON_TIM_MAN_UPDATE_SHIFT(c))
+#define PWM_TCON_TIM_MAN_UPDATE_UPDATE(c)      (0x1 << PWM_TCON_TIM_MAN_UPDATE_SHIFT(c))
+
+#define PWM_TCON_TIM_OUTPUT_INV_SHIFT(c)       (PWM_TCON_TIM_BIT_OFFSET(c) + 2)
+#define PWM_TCON_TIM_OUTPUT_INV_MASK(c)                (0x1 << PWM_TCON_TIM_OUTPUT_INV_SHIFT(c))
+#define PWM_TCON_TIM_OUTPUT_INV_OFF(c)         (0x0 << PWM_TCON_TIM_OUTPUT_INV_SHIFT(c))
+#define PWM_TCON_TIM_OUTPUT_INV_ON(c)          (0x1 << PWM_TCON_TIM_OUTPUT_INV_SHIFT(c))
+
+#define PWM_TCON_TIM_AUTO_RELOAD_SHIFT(c)      (PWM_TCON_TIM_BIT_OFFSET(c) + 3)
+#define PWM_TCON_TIM_AUTO_RELOAD_MASK(c)       (0x1 << PWM_TCON_TIM_AUTO_RELOAD_SHIFT(c))
+#define PWM_TCON_TIM_AUTO_RELOAD_OFF(c)                (0x0 << PWM_TCON_TIM_AUTO_RELOAD_SHIFT(c))
+#define PWM_TCON_TIM_AUTO_RELOAD_ON(c)         (0x1 << PWM_TCON_TIM_AUTO_RELOAD_SHIFT(c))
+
+#define PWM_TCON_TIM0_STARTSTOP_SHIFT          PWM_TCON_TIM_BIT_OFFSET(0)
+#define PWM_TCON_TIM0_STARTSTOP_MASK           (0x1 << PWM_TCON_TIM_STARTSTOP_SHIFT(0))
+#define PWM_TCON_TIM0_STARTSTOP_STOP           (0x0 << PWM_TCON_TIM_STARTSTOP_SHIFT(0))
+#define PWM_TCON_TIM0_STARTSTOP_START          (0x1 << PWM_TCON_TIM_STARTSTOP_SHIFT(0))
+
+#define PWM_TCON_TIM0_MAN_UPDATE_SHIFT         (PWM_TCON_TIM_BIT_OFFSET(0) + 1)
+#define PWM_TCON_TIM0_MAN_UPDATE_MASK          (0x1 << PWM_TCON_TIM_MAN_UPDATE_SHIFT(0))
+#define PWM_TCON_TIM0_MAN_UPDATE_NOP           (0x0 << PWM_TCON_TIM_MAN_UPDATE_SHIFT(0))
+#define PWM_TCON_TIM0_MAN_UPDATE_UPDATE                (0x1 << PWM_TCON_TIM_MAN_UPDATE_SHIFT(0))
+
+#define PWM_TCON_TIM0_OUTPUT_INV_SHIFT         (PWM_TCON_TIM_BIT_OFFSET(0) + 2)
+#define PWM_TCON_TIM0_OUTPUT_INV_MASK          (0x1 << PWM_TCON_TIM_OUTPUT_INV_SHIFT(0))
+#define PWM_TCON_TIM0_OUTPUT_INV_OFF           (0x0 << PWM_TCON_TIM_OUTPUT_INV_SHIFT(0))
+#define PWM_TCON_TIM0_OUTPUT_INV_ON                    (0x1 << PWM_TCON_TIM_OUTPUT_INV_SHIFT(0))
+
+#define PWM_TCON_TIM0_AUTO_RELOAD_SHIFT                (PWM_TCON_TIM_BIT_OFFSET(0) + 3)
+#define PWM_TCON_TIM0_AUTO_RELOAD_MASK         (0x1 << PWM_TCON_TIM_AUTO_RELOAD_SHIFT(0))
+#define PWM_TCON_TIM0_AUTO_RELOAD_OFF          (0x0 << PWM_TCON_TIM_AUTO_RELOAD_SHIFT(0))
+#define PWM_TCON_TIM0_AUTO_RELOAD_ON           (0x1 << PWM_TCON_TIM_AUTO_RELOAD_SHIFT(0))
+
+#define PWM_TCON_TIM0_DEADZONE_SHIFT           (PWM_TCON_TIM_BIT_OFFSET(0) + 4)
+#define PWM_TCON_TIM0_DEADZONE_MASK                    (0x1 << PWM_TCON_TIM0_DEADZONE_SHIFT)
+#define PWM_TCON_TIM0_DEADZONE_DISABLE         (0x0 << PWM_TCON_TIM0_DEADZONE_SHIFT)
+#define PWM_TCON_TIM0_DEADZONE_ENABLE          (0x1 << PWM_TCON_TIM0_DEADZONE_SHIFT)
+
+#define PWM_TCON_TIM1_STARTSTOP_SHIFT          PWM_TCON_TIM_BIT_OFFSET(1)
+#define PWM_TCON_TIM1_STARTSTOP_MASK           (0x1 << PWM_TCON_TIM1_STARTSTOP_SHIFT)
+#define PWM_TCON_TIM1_STARTSTOP_STOP           (0x0 << PWM_TCON_TIM1_STARTSTOP_SHIFT)
+#define PWM_TCON_TIM1_STARTSTOP_START          (0x1 << PWM_TCON_TIM1_STARTSTOP_SHIFT)
+
+#define PWM_TCON_TIM1_MAN_UPDATE_SHIFT         (PWM_TCON_TIM_BIT_OFFSET(1) + 1)
+#define PWM_TCON_TIM1_MAN_UPDATE_MASK          (0x1 << PWM_TCON_TIM1_MAN_UPDATE_SHIFT)
+#define PWM_TCON_TIM1_MAN_UPDATE_NOP           (0x0 << PWM_TCON_TIM1_MAN_UPDATE_SHIFT)
+#define PWM_TCON_TIM1_MAN_UPDATE_UPDATE                (0x1 << PWM_TCON_TIM1_MAN_UPDATE_SHIFT)
+
+#define PWM_TCON_TIM1_OUTPUT_INV_SHIFT         (PWM_TCON_TIM_BIT_OFFSET(1) + 2)
+#define PWM_TCON_TIM1_OUTPUT_INV_MASK          (0x1 << PWM_TCON_TIM1_OUTPUT_INV_SHIFT)
+#define PWM_TCON_TIM1_OUTPUT_INV_OFF           (0x0 << PWM_TCON_TIM1_OUTPUT_INV_SHIFT)
+#define PWM_TCON_TIM1_OUTPUT_INV_ON                    (0x1 << PWM_TCON_TIM1_OUTPUT_INV_SHIFT)
+
+#define PWM_TCON_TIM1_AUTO_RELOAD_SHIFT                (PWM_TCON_TIM_BIT_OFFSET(1) + 3)
+#define PWM_TCON_TIM1_AUTO_RELOAD_MASK         (0x1 << PWM_TCON_TIM1_AUTO_RELOAD_SHIFT)
+#define PWM_TCON_TIM1_AUTO_RELOAD_OFF          (0x0 << PWM_TCON_TIM1_AUTO_RELOAD_SHIFT)
+#define PWM_TCON_TIM1_AUTO_RELOAD_ON           (0x1 << PWM_TCON_TIM1_AUTO_RELOAD_SHIFT)
+
+#define PWM_TCON_TIM2_STARTSTOP_SHIFT          PWM_TCON_TIM_BIT_OFFSET(2)
+#define PWM_TCON_TIM2_STARTSTOP_MASK           (0x1 << PWM_TCON_TIM2_STARTSTOP_SHIFT)
+#define PWM_TCON_TIM2_STARTSTOP_STOP           (0x0 << PWM_TCON_TIM2_STARTSTOP_SHIFT)
+#define PWM_TCON_TIM2_STARTSTOP_START          (0x1 << PWM_TCON_TIM2_STARTSTOP_SHIFT)
+
+#define PWM_TCON_TIM2_MAN_UPDATE_SHIFT         (PWM_TCON_TIM_BIT_OFFSET(2) + 1)
+#define PWM_TCON_TIM2_MAN_UPDATE_MASK          (0x1 << PWM_TCON_TIM2_MAN_UPDATE_SHIFT)
+#define PWM_TCON_TIM2_MAN_UPDATE_NOP           (0x0 << PWM_TCON_TIM2_MAN_UPDATE_SHIFT)
+#define PWM_TCON_TIM2_MAN_UPDATE_UPDATE                (0x1 << PWM_TCON_TIM2_MAN_UPDATE_SHIFT)
+
+#define PWM_TCON_TIM2_OUTPUT_INV_SHIFT         (PWM_TCON_TIM_BIT_OFFSET(2) + 2)
+#define PWM_TCON_TIM2_OUTPUT_INV_MASK          (0x1 << PWM_TCON_TIM2_OUTPUT_INV_SHIFT)
+#define PWM_TCON_TIM2_OUTPUT_INV_OFF           (0x0 << PWM_TCON_TIM2_OUTPUT_INV_SHIFT)
+#define PWM_TCON_TIM2_OUTPUT_INV_ON                    (0x1 << PWM_TCON_TIM2_OUTPUT_INV_SHIFT)
+
+#define PWM_TCON_TIM2_AUTO_RELOAD_SHIFT                (PWM_TCON_TIM_BIT_OFFSET(2) + 3)
+#define PWM_TCON_TIM2_AUTO_RELOAD_MASK         (0x1 << PWM_TCON_TIM2_AUTO_RELOAD_SHIFT)
+#define PWM_TCON_TIM2_AUTO_RELOAD_OFF          (0x0 << PWM_TCON_TIM2_AUTO_RELOAD_SHIFT)
+#define PWM_TCON_TIM2_AUTO_RELOAD_ON           (0x1 << PWM_TCON_TIM2_AUTO_RELOAD_SHIFT)
+
+#define PWM_TCON_TIM3_STARTSTOP_SHIFT          PWM_TCON_TIM_BIT_OFFSET(3)
+#define PWM_TCON_TIM3_STARTSTOP_MASK           (0x1 << PWM_TCON_TIM3_STARTSTOP_SHIFT)
+#define PWM_TCON_TIM3_STARTSTOP_STOP           (0x0 << PWM_TCON_TIM3_STARTSTOP_SHIFT)
+#define PWM_TCON_TIM3_STARTSTOP_START          (0x1 << PWM_TCON_TIM3_STARTSTOP_SHIFT)
+
+#define PWM_TCON_TIM3_MAN_UPDATE_SHIFT         (PWM_TCON_TIM_BIT_OFFSET(3) + 1)
+#define PWM_TCON_TIM3_MAN_UPDATE_MASK          (0x1 << PWM_TCON_TIM3_MAN_UPDATE_SHIFT)
+#define PWM_TCON_TIM3_MAN_UPDATE_NOP           (0x0 << PWM_TCON_TIM3_MAN_UPDATE_SHIFT)
+#define PWM_TCON_TIM3_MAN_UPDATE_UPDATE                (0x1 << PWM_TCON_TIM3_MAN_UPDATE_SHIFT)
+
+#define PWM_TCON_TIM3_OUTPUT_INV_SHIFT         (PWM_TCON_TIM_BIT_OFFSET(3) + 2)
+#define PWM_TCON_TIM3_OUTPUT_INV_MASK          (0x1 << PWM_TCON_TIM3_OUTPUT_INV_SHIFT)
+#define PWM_TCON_TIM3_OUTPUT_INV_OFF           (0x0 << PWM_TCON_TIM3_OUTPUT_INV_SHIFT)
+#define PWM_TCON_TIM3_OUTPUT_INV_ON                    (0x1 << PWM_TCON_TIM3_OUTPUT_INV_SHIFT)
+
+#define PWM_TCON_TIM3_AUTO_RELOAD_SHIFT                (PWM_TCON_TIM_BIT_OFFSET(3) + 3)
+#define PWM_TCON_TIM3_AUTO_RELOAD_MASK         (0x1 << PWM_TCON_TIM3_AUTO_RELOAD_SHIFT)
+#define PWM_TCON_TIM3_AUTO_RELOAD_OFF          (0x0 << PWM_TCON_TIM3_AUTO_RELOAD_SHIFT)
+#define PWM_TCON_TIM3_AUTO_RELOAD_ON           (0x1 << PWM_TCON_TIM3_AUTO_RELOAD_SHIFT)
+
+/* TINT_CSTAT ***************************************************************/
+#define PWM_TINT_CSTAT_TIM0_INTMASK_SHIFT      0
+#define PWM_TINT_CSTAT_TIM0_INTMASK_MASK       (0x1 << PWM_TINT_CSTAT_TIM0_INTMASk_SHIFT)
+
+#define PWM_TINT_CSTAT_TIM1_INTMASK_SHIFT      1
+#define PWM_TINT_CSTAT_TIM1_INTMASK_MASK       (0x1 << PWM_TINT_CSTAT_TIM1_INTMASK_SHIFT)
+
+#define PWM_TINT_CSTAT_TIM2_INTMASK_SHIFT      2
+#define PWM_TINT_CSTAT_TIM2_INTMASK_MASK       (0x1 << PWM_TINT_CSTAT_TIM2_INTMASK_SHIFT)
+
+#define PWM_TINT_CSTAT_TIM3_INTMASK_SHIFT      3
+#define PWM_TINT_CSTAT_TIM3_INTMASK_MASK       (0x1 << PWM_TINT_CSTAT_TIM3_INTMASK_SHIFT)
+
+#define PWM_TINT_CSTAT_TIM0_INTPND_SHIFT       5
+#define PWM_TINT_CSTAT_TIM0_INTPND_MASK                (0x1 << PWM_TINT_CSTAT_TIM0_INTPND_SHIFT)
+
+#define PWM_TINT_CSTAT_TIM1_INTPND_SHIFT       6
+#define PWM_TINT_CSTAT_TIM1_INTPND_MASK                (0x1 << PWM_TINT_CSTAT_TIM1_INTPND_SHIFT)
+
+#define PWM_TINT_CSTAT_TIM2_INTPND_SHIFT       7
+#define PWM_TINT_CSTAT_TIM2_INTPND_MASK                (0x1 << PWM_TINT_CSTAT_TIM2_INTPND_SHIFT)
+
+#define PWM_TINT_CSTAT_TIM3_INTPND_SHIFT       8
+#define PWM_TINT_CSTAT_TIM3_INTPND_MASK                (0x1 << PWM_TINT_CSTAT_TIM3_INTPND_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_S5J_CHIP_S5JT200_PWM_H */
index d337446..8b1c388 100644 (file)
 /****************************************************************************
  * arch/arm/src/s5j/s5j_pwm.c
  *
- *   Copyright (C) 2013-2014 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gnutt@nuttx.org>
- *
- * The Samsung sample code has a BSD compatible license that requires this
- * copyright notice:
- *
- *   Copyright (c) 2016 Samsung Electronics, Inc.
- *   All rights reserved.
+ *   Copyright (C) 2011-2012, 2014 Gregory Nutt. All rights reserved.
+ *   Authors: Gregory Nutt <gnutt@nuttx.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * POSSIBILITY OF SUCH DAMAGE.
  *
  */
+
 /****************************************************************************
  * Included Files
  ****************************************************************************/
 #include <tinyara/config.h>
 
 #include <sys/types.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-#include <poll.h>
-#include <errno.h>
+#include <assert.h>
 #include <debug.h>
-#include <tinyara/pwm.h>
+#include <errno.h>
 
-#include <arch/chip/irq.h>
+#include <tinyara/pwm.h>
 
-#include "chip.h"
 #include "up_arch.h"
-
 #include "s5j_pwm.h"
 #include "s5j_gpio.h"
 
 /****************************************************************************
- * Static Function Prototypes
+ * Pre-processor definitions
  ****************************************************************************/
 
 /****************************************************************************
- * Private Data
+ * Private Types
  ****************************************************************************/
-/* This is the list of lower half PWM driver methods used by the upper half driver */
-
-static bool pwm_initialized[2] = { false, false };
-
-static const struct pwm_ops_s g_pwmops = {
-       .setup = s5j_pwm_setup,
-       .shutdown = s5j_pwm_shutdown,
-       .start = s5j_pwm_start,
-       .stop = s5j_pwm_stop,
-       .ioctl = s5j_pwm_ioctl,
-};
-
-static struct s5j_pwmtimer_s g_pwmdev[TOTAL_NUMBER_OF_TIMER];
-
-/* PWM/Timer Definitions ****************************************************/
-/* The following definitions are used to identify the various time types */
+struct s5j_pwmtimer_s {
+       FAR const struct pwm_ops_s *ops;
 
-struct s5j_pwm_intdata intdata[MAX_NO_PWM] = {
-       {
-               .pwm_no = 0,
-               .int_count = 0,
-               .reload = (1 << 3),
-               .manual_update = (1 << 1),
-               .start = (1 << 0),
-               .invert = (1 << 2),
-               .prescaler = 0,
-               .div_mux = 0,
-       },
-       {
-               .pwm_no = 1,
-               .int_count = 0,
-               .reload = (1 << 11),
-               .manual_update = (1 << 9),
-               .start = (1 << 8),
-               .invert = (1 << 10),
-               .prescaler = 0,
-               .div_mux = 4,
-       },
-       {
-               .pwm_no = 2,
-               .int_count = 0,
-               .reload = (1 << 15),
-               .manual_update = (1 << 13),
-               .start = (1 << 12),
-               .invert = (1 << 14),
-               .prescaler = 8,
-               .div_mux = 8,
-       },
-       {
-               .pwm_no = 3,
-               .int_count = 0,
-               .reload = (1 << 19),
-               .manual_update = (1 << 17),
-               .start = (1 << 16),
-               .invert = (1 << 18),
-               .prescaler = 8,
-               .div_mux = 12,
-       },
+       unsigned int base;
+       uint8_t id;
+       uint16_t pincfg;
 };
 
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
+static unsigned int s5j_get_oscclk(void)
+{
+       return 26000000;
+}
 
-/****************************************************************************
- * Name: s5j_pwm_interrupt
- *
- * Description:
- *   Handle timer interrupts.
- *
- * Input parameters:
- *   priv - A reference to the lower half PWM driver state structure
- *
- * Returned Value:
- *   Zero on success; a negated errno value on failure
- *
- ****************************************************************************/
-static int s5j_pwm_interrupt(struct s5j_pwmtimer_s *priv)
+static uint32_t pwm_getreg32(struct s5j_pwmtimer_s *priv, int offset)
 {
-       return 0;
+       return getreg32(priv->base + offset);
 }
 
-/****************************************************************************
- * Name: s5j_pwm_timer_interrupt
- *
- * Description:
- *   Handle pwm 0..4 interrupts.
- *
- * Input parameters:
- *   Standard NuttX interrupt inputs
- *
- * Returned Value:
- *   Zero on success; a negated errno value on failure
- *
- ****************************************************************************/
-static int s5j_pwm_timer_interrupt(int irq, void *context, void *arg)
+static void pwm_putreg32(struct s5j_pwmtimer_s *priv, int offset, uint32_t value)
 {
-       signed int pwm_no;
-       signed int irq_no;
-       signed int int_stat;
-       FAR struct s5j_pwmtimer_s *priv;
+       putreg32(value, priv->base + offset);
+}
 
-       irq_no = irq - IRQ_PWM0_0;
+static void pwm_modifyreg32(struct s5j_pwmtimer_s *priv, int offset,
+                               uint32_t clearbits, uint32_t setbits)
+{
+       modifyreg32(priv->base + offset, clearbits, setbits);
+}
+
+static unsigned int pwm_get_prescaler(struct s5j_pwmtimer_s *priv)
+{
+       unsigned int tcfg0 = pwm_getreg32(priv, S5J_PWM_TCFG0_OFFSET);
 
-       if (irq_no > 4) {
-               pwm_no = irq_no - 1;
-       } else {
-               pwm_no = irq_no;
+       if (priv->id == 0 || priv->id == 1) {
+               return (tcfg0 & PWM_TCFG0_PRESCALER0_MASK) >> PWM_TCFG0_PRESCALER0_SHIFT;
        }
 
-       priv = &g_pwmdev[pwm_no];
+       return (tcfg0 & PWM_TCFG0_PRESCALER1_MASK) >> PWM_TCFG0_PRESCALER1_SHIFT;
+}
 
-       /* Clear interrupt pending register */
-       int_stat = getreg32(priv->base + TINT_CSTAT) & 0x1F;
-       int_stat |= (1 << (5 + irq_no));
-       putreg32(int_stat, priv->base + TINT_CSTAT);
+static unsigned int pwm_get_divider(struct s5j_pwmtimer_s *priv)
+{
+       unsigned int tcfg1 = pwm_getreg32(priv, S5J_PWM_TCFG1_OFFSET);
 
-       return s5j_pwm_interrupt(priv);
+       return (tcfg1 & PWM_TCFG1_DIVIDER_MUX_MASK(priv->id)) >> PWM_TCFG1_DIVIDER_MUX_SHIFT(priv->id);
+}
+
+static unsigned int pwm_clk_freq(struct s5j_pwmtimer_s *priv)
+{
+       return (s5j_get_oscclk() / (pwm_get_prescaler(priv) + 1)) >> pwm_get_divider(priv);
 }
 
 /****************************************************************************
@@ -223,148 +147,92 @@ static int s5j_pwm_timer_interrupt(int irq, void *context, void *arg)
  *   logic at power up.
  *
  ****************************************************************************/
-
 static int s5j_pwm_setup(FAR struct pwm_lowerhalf_s *dev)
 {
        FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
 
-       int channel;
-
-       channel = priv->id;
-
-       /* skip channel4 */
-       if (channel >= 4) {
-               channel += 1;
-       }
-
-       if (channel == 0) {
-               s5j_configgpio(GPIO_PWM_TOUT0);
-       } else if (channel == 1) {
-               s5j_configgpio(GPIO_PWM_TOUT1);
-       } else if (channel == 2) {
-               s5j_configgpio(GPIO_PWM_TOUT2);
-       } else if (channel == 3) {
-               s5j_configgpio(GPIO_PWM_TOUT3);
-       } else if (channel == 5) {
-               s5j_configgpio(GPIO_PWM_TOUT5);
-       } else if (channel == 6) {
-               s5j_configgpio(GPIO_PWM_TOUT6);
-       }
-
-       return OK;
+       return s5j_configgpio(priv->pincfg);
 }
 
 /****************************************************************************
- * Name: s5j_pwm_shutdown
+ * Name: s5j_pwm_start
  *
  * Description:
- *   This method is called when the driver is closed.  The lower half driver
- *   stop pulsed output, free any resources, disable the timer hardware, and
- *   put the system into the lowest possible power usage state
+ *   (Re-)initialize the timer resources and start the pulsed output
  *
  * Input parameters:
  *   dev - A reference to the lower half PWM driver state structure
+ *   info - A reference to the characteristics of the pulsed output
  *
  * Returned Value:
  *   Zero on success; a negated errno value on failure
  *
  ****************************************************************************/
-
-static int s5j_pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
+static int s5j_pwm_start(FAR struct pwm_lowerhalf_s *dev,
+                                                FAR const struct pwm_info_s *info)
 {
+       uint32_t tcntb;
+       uint32_t tcmpb;
        FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       int channel;
 
-       channel = priv->id;
+       tcntb = pwm_clk_freq(priv) / info->frequency - 1;
+       tcmpb = (((tcntb + 1) * info->duty) / 65536) - 1;
 
-       /* skip channel4 */
-       if (channel >= 4) {
-               channel += 1;
-       }
+       pwm_putreg32(priv, S5J_PWM_TCNTB_OFFSET(priv->id), tcntb);
+       pwm_putreg32(priv, S5J_PWM_TCMPB_OFFSET(priv->id), tcmpb);
 
-       if (channel == 0) {
-               s5j_unconfiggpio(GPIO_PWM_TOUT0);
-       } else if (channel == 1) {
-               s5j_unconfiggpio(GPIO_PWM_TOUT1);
-       } else if (channel == 2) {
-               s5j_unconfiggpio(GPIO_PWM_TOUT2);
-       } else if (channel == 3) {
-               s5j_unconfiggpio(GPIO_PWM_TOUT3);
-       } else if (channel == 5) {
-               s5j_unconfiggpio(GPIO_PWM_TOUT5);
-       } else if (channel == 6) {
-               s5j_unconfiggpio(GPIO_PWM_TOUT6);
-       }
+       pwm_modifyreg32(priv, S5J_PWM_TCON_OFFSET,
+                                       PWM_TCON_TIM_MAN_UPDATE_MASK(priv->id),
+                                       PWM_TCON_TIM_MAN_UPDATE_UPDATE(priv->id));
 
-       /* Make sure that the output has been stopped */
-       s5j_pwm_stop(dev);
+       /* Trigger to start */
+       pwm_modifyreg32(priv, S5J_PWM_TCON_OFFSET,
+                                       PWM_TCON_TIM_STARTSTOP_MASK(priv->id) |
+                                       PWM_TCON_TIM_MAN_UPDATE_MASK(priv->id) |
+                                       PWM_TCON_TIM_AUTO_RELOAD_MASK(priv->id),
+                                       PWM_TCON_TIM_STARTSTOP_START(priv->id) |
+                                       PWM_TCON_TIM_MAN_UPDATE_NOP(priv->id) |
+                                       PWM_TCON_TIM_AUTO_RELOAD_ON(priv->id));
 
        return OK;
 }
 
 /****************************************************************************
- * Name: s5j_pwm_start
+ * Name: s5j_pwm_stop
  *
  * Description:
- *   (Re-)initialize the timer resources and start the pulsed output
+ *   Stop the pulsed output and reset the timer resources
  *
  * Input parameters:
  *   dev - A reference to the lower half PWM driver state structure
- *   info - A reference to the characteristics of the pulsed output
  *
  * Returned Value:
  *   Zero on success; a negated errno value on failure
  *
+ * Assumptions:
+ *   This function is called to stop the pulsed output at anytime.  This
+ *   method is also called from the timer interrupt handler when a repetition
+ *   count expires... automatically stopping the timer.
+ *
  ****************************************************************************/
-#ifdef CONFIG_PWM_PULSECOUNT
-static int s5j_pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info, FAR void *handle)
-#else
-static int s5j_pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info)
-#endif
+static int s5j_pwm_stop(FAR struct pwm_lowerhalf_s *dev)
 {
        FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       struct s5j_pwm_intdata *pwm_data = priv->intdata;
-
-       signed int tcon, int_stat;
-#ifdef CONFIG_PWM_PULSECOUNT
-       priv->callback = handle;
-#endif
-
-       s5j_pwm_set_frequency_dutycycle(dev, info->frequency, info->duty);
-
-       /* Enable interrupt */
-       int_stat = getreg32(priv->base + TINT_CSTAT) & 0x1F;
-       int_stat |= (1 << priv->id);
-       putreg32(int_stat, priv->base + TINT_CSTAT);
-
-       tcon = getreg32(priv->base + TCON);
-
-       /* interrupt enable */
-       //up_enable_irq(priv->irq);
 
-       /* Manual update */
-       putreg32(tcon | pwm_data->manual_update, priv->base + TCON);
+       pwm_modifyreg32(priv, S5J_PWM_TCON_OFFSET,
+                                       PWM_TCON_TIM_STARTSTOP_MASK(priv->id),
+                                       PWM_TCON_TIM_STARTSTOP_STOP(priv->id));
 
-#if 0
-       if (type == TIMER_TYPE_ONE_SHOT) {      /* ONESHOT */
-               tcon &= ~(pwm_data->reload);
-       } else                                          /* INTERVAL */
-#endif
-
-               tcon |= pwm_data->reload;
-
-       tcon |= pwm_data->start;
-
-       putreg32(tcon, priv->base + TCON);
-
-       return 0;
+       return OK;
 }
 
 /****************************************************************************
- * Name: s5j_pwm_stop
+ * Name: s5j_pwm_shutdown
  *
  * Description:
- *   Stop the pulsed output and reset the timer resources
+ *   This method is called when the driver is closed.  The lower half driver
+ *   stop pulsed output, free any resources, disable the timer hardware, and
+ *   put the system into the lowest possible power usage state
  *
  * Input parameters:
  *   dev - A reference to the lower half PWM driver state structure
@@ -372,191 +240,16 @@ static int s5j_pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_i
  * Returned Value:
  *   Zero on success; a negated errno value on failure
  *
- * Assumptions:
- *   This function is called to stop the pulsed output at anytime.  This
- *   method is also called from the timer interrupt handler when a repetition
- *   count expires... automatically stopping the timer.
- *
  ****************************************************************************/
-
-static int s5j_pwm_stop(FAR struct pwm_lowerhalf_s *dev)
-{
-       FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       struct s5j_pwm_intdata *pwm_data = priv->intdata;
-
-       signed int tcon, int_stat;
-
-       /* Disable interrupt */
-       int_stat = getreg32(priv->base + TINT_CSTAT) & 0x1F;
-       int_stat &= ~(1 << pwm_data->pwm_no);
-       putreg32(int_stat, priv->base + TINT_CSTAT);
-
-       tcon = getreg32(priv->base + TCON);
-       tcon &= ~pwm_data->start;
-       tcon &= ~pwm_data->reload;
-       tcon &= ~pwm_data->invert;
-       putreg32(tcon, priv->base + TCON);
-
-       /* interrupt disable */
-       up_disable_irq(priv->irq);
-
-       priv->callback = NULL;
-
-       return 0;
-}
-
-static int s5j_pwm_set_dutycycle(FAR struct pwm_lowerhalf_s *dev, signed int duty)
-{
-       FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       struct s5j_pwm_intdata *pwm_data = priv->intdata;
-       signed int tcntb;
-       signed int tcmpb;
-       signed int id;
-       int64_t tmp;
-
-       if (duty > 100) {
-               duty = 100;
-       }
-
-       priv->dutycycle = duty;
-       id = pwm_data->pwm_no;
-
-       tcntb = getreg32(priv->base + TCNTB(id));
-
-       tmp = ((tcntb + 1) * duty) / 100 - 1;   // duty range :0 ~ 100
-       tcmpb = (signed int)tmp;
-
-       putreg32(tcmpb, priv->base + TCMPB(id));
-
-       return 0;
-}
-
-static int s5j_pwm_set_pulsewidth(FAR struct pwm_lowerhalf_s *dev, signed int frequency)
-{
-       FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       struct s5j_pwm_intdata *pwm_data = priv->intdata;
-       signed int tcntb;
-       signed int id;
-
-       signed int timerclockfreq;
-
-       timerclockfreq = PWM_PCLK / priv->pre_scaler / priv->divider;
-       if ((timerclockfreq / 2) < frequency) {
-               //PWM can't be generate the freq
-               frequency = timerclockfreq / 2;
-       }
-
-       priv->freq = frequency;
-       id = pwm_data->pwm_no;
-
-       tcntb = (priv->timer_pclk / priv->pre_scaler / priv->divider / frequency) - 1;
-       putreg32(tcntb, priv->base + TCNTB(id));
-
-       return 0;
-}
-
-static int s5j_pwm_set_frequency_dutycycle(FAR struct pwm_lowerhalf_s *dev, signed int frequency, signed int duty)
-{
-       s5j_pwm_set_pulsewidth(dev, frequency);
-       s5j_pwm_set_dutycycle(dev, duty);
-
-       return 0;
-}
-
-/* scaler_val : 1 ~ 256 */
-static int s5j_pwm_set_prescaler(FAR struct pwm_lowerhalf_s *dev, signed int scaler_val)
-{
-       FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       struct s5j_pwm_intdata *pwm_data = priv->intdata;
-
-       int i;
-       signed int id;
-       signed int tcntb;
-       signed int val;
-       signed int nPWM;
-       //unsigned long flag;
-
-       if (priv->id < 4) {
-               nPWM = 0;
-       } else {
-               nPWM = 4;
-       }
-
-       if (pwm_data->pwm_no < 2) {
-               for (i = 0; i < 2; i++) {
-                       g_pwmdev[nPWM + i].pre_scaler = scaler_val;
-
-                       pwm_data = priv->intdata;
-
-                       if ((getreg32(priv->base + TCON) & (g_pwmdev[nPWM + i].intdata->start)) != 0) {
-                               id = g_pwmdev[nPWM + i].intdata->pwm_no;
-
-                               tcntb = (g_pwmdev[nPWM + i].timer_pclk / g_pwmdev[nPWM + i].pre_scaler / g_pwmdev[nPWM + i].divider / g_pwmdev[nPWM + i].freq) - 1;
-                               putreg32(tcntb, g_pwmdev[nPWM + i].base + TCNTB(id));
-                       }
-               }
-       } else {
-               for (i = 2; i < 4; i++) {
-                       g_pwmdev[nPWM + i].pre_scaler = scaler_val;
-
-                       if ((getreg32(priv->base + TCON) & (g_pwmdev[nPWM + i].intdata->start)) != 0) {
-                               id = g_pwmdev[nPWM + i].intdata->pwm_no;
-
-                               tcntb = (g_pwmdev[nPWM + i].timer_pclk / g_pwmdev[nPWM + i].pre_scaler / g_pwmdev[nPWM + i].divider / g_pwmdev[nPWM + i].freq) - 1;
-                               putreg32(tcntb, g_pwmdev[nPWM + i].base + TCNTB(id));
-                       }
-               }
-       }
-
-       val = getreg32(priv->base + TCFG0);
-       val &= ~(0xFF << pwm_data->prescaler);
-       val |= ((scaler_val - 1) << pwm_data->prescaler);
-       putreg32(val, priv->base + TCFG0);
-
-       return 0;
-}
-
-/* scaler_val : 0 ~ 4 */
-static int s5j_pwm_set_divider(FAR struct pwm_lowerhalf_s *dev, signed int div_val)
+static int s5j_pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
 {
        FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       struct s5j_pwm_intdata *pwm_data = priv->intdata;
-       signed int val;
-
-       switch (div_val) {
-       case 0: {
-               priv->divider = 1;
-       }
-       break;
-       case 1: {
-               priv->divider = 2;
-       }
-       break;
-       case 2: {
-               priv->divider = 4;
-       }
-       break;
-       case 3: {
-               priv->divider = 8;
-       }
-       break;
-       case 4: {
-               priv->divider = 16;
-       }
-       break;
-       default:
-               return -EINVAL;
-       }
-
-       val = getreg32(priv->base + TCFG1);
-       val &= ~(0xF << pwm_data->div_mux);
-       val |= (div_val << pwm_data->div_mux);
-       putreg32(val, priv->base + TCFG1);
 
-       s5j_pwm_set_pulsewidth(dev, priv->freq);
-       s5j_pwm_set_dutycycle(dev, priv->dutycycle);
+       /* Make sure that the output has been stopped */
+       s5j_pwm_stop(dev);
 
-       return 0;
+       /* Then put the GPIO pins back to the default state */
+       return s5j_unconfiggpio(priv->pincfg);
 }
 
 /****************************************************************************
@@ -574,54 +267,80 @@ static int s5j_pwm_set_divider(FAR struct pwm_lowerhalf_s *dev, signed int div_v
  *   Zero on success; a negated errno value on failure
  *
  ****************************************************************************/
-
-static int s5j_pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg)
+static int s5j_pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd,
+                                                unsigned long arg)
 {
-       FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       signed int val, tcfg0;
-
-       val = (signed int)arg;
+       return -ENOTTY;
+}
 
-       switch (cmd) {
-       case PWM_SET_PRESCALER: {
-               return s5j_pwm_set_prescaler(dev, val);
-       }
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+static const struct pwm_ops_s g_pwm_ops = {
+       .setup          = s5j_pwm_setup,
+       .shutdown       = s5j_pwm_shutdown,
+       .start          = s5j_pwm_start,
+       .stop           = s5j_pwm_stop,
+       .ioctl          = s5j_pwm_ioctl,
+};
 
-       case PWM_SET_DIVIDER: {
-               return s5j_pwm_set_divider(dev, val);
-       }
+#ifdef CONFIG_S5J_PWM0
+static struct s5j_pwmtimer_s g_pwm0_0 = {
+       .ops    = &g_pwm_ops,
+       .id             = 0,
+       .pincfg = GPIO_PWM_TOUT0,
+       .base   = S5J_PWM0_BASE,
+};
+#endif
 
-       case PWM_SET_DEADZONE: {
-               if (val >= 256) {
-                       val = 255;
-               }
-               tcfg0 = getreg32(priv->base + TCFG0);
-               tcfg0 &= ~(0xFF << 16);
-               tcfg0 |= (val << 16);
-               putreg32(tcfg0, priv->base + TCFG0);
-       }
-       break;
+#ifdef CONFIG_S5J_PWM1
+static struct s5j_pwmtimer_s g_pwm0_1 = {
+       .ops    = &g_pwm_ops,
+       .id             = 1,
+       .pincfg = GPIO_PWM_TOUT1,
+       .base   = S5J_PWM0_BASE,
+};
+#endif
 
-       case PWM_SET_TCMP: {
-               if (TCMPB(priv->id) != TREG_INVAL) {
-                       putreg32(val, priv->base + TCMPB(priv->id));
-               }
-       }
-       break;
+#ifdef CONFIG_S5J_PWM2
+static struct s5j_pwmtimer_s g_pwm0_2 = {
+       .ops    = &g_pwm_ops,
+       .id             = 2,
+       .pincfg = GPIO_PWM_TOUT2,
+       .base   = S5J_PWM0_BASE,
+};
+#endif
 
-       case PWM_SET_DUTY_CYCLE: {
-               s5j_pwm_set_dutycycle(dev, val);
-       }
-       break;
+#ifdef CONFIG_S5J_PWM3
+static struct s5j_pwmtimer_s g_pwm0_3 = {
+       .ops    = &g_pwm_ops,
+       .id             = 3,
+       .pincfg = GPIO_PWM_TOUT3,
+       .base   = S5J_PWM0_BASE,
+};
+#endif
 
-       default:
-               break;
-       }
+#ifdef CONFIG_S5J_PWM4
+static struct s5j_pwmtimer_s g_pwm1_0 = {
+       .ops    = &g_pwm_ops,
+       .id             = 0,
+       .pincfg = GPIO_PWM_TOUT5,
+       .base   = S5J_PWM1_BASE,
+};
+#endif
 
-       lldbg("TIMER%d\n", priv->id);
+#ifdef CONFIG_S5J_PWM5
+static struct s5j_pwmtimer_s g_pwm1_1 = {
+       .ops    = &g_pwm_ops,
+       .id             = 1,
+       .pincfg = GPIO_PWM_TOUT6,
+       .base   = S5J_PWM1_BASE,
+};
+#endif
 
-       return 0;
-}
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
 
 /****************************************************************************
  * Name: s5j_pwminitialize
@@ -630,86 +349,52 @@ static int s5j_pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long
  *   Initialize one timer for use with the upper_level PWM driver.
  *
  * Input Parameters:
- *   timer - A number identifying the timer use.  The number of valid timer
- *     IDs varies with the S5J MCU and MCU family but is somewhere in
- *     the range of {1,..,14}.
+ *   timer - A number identifying the timer use. The number of valid timer
+ *     IDs varies with the S5J family but is somewhere in the range of
+ *     {0,...,5}.
  *
  * Returned Value:
- *   On success, a pointer to the S5J lower half PWM driver is returned.
+ *   On success, a pointer to the lower-half PWM driver is returned.
  *   NULL is returned on any failure.
  *
  ****************************************************************************/
 FAR struct pwm_lowerhalf_s *s5j_pwminitialize(int timer)
 {
-       struct s5j_pwmtimer_s *lower, *tmp;
-
-       unsigned int i;
-       unsigned int nPWM;
-       unsigned int nTimer;
-       unsigned int PWM_BASE_ADDR;
-
-       if (timer < 4) {
-               nPWM = 0;
-               nTimer = timer;
-               PWM_BASE_ADDR = PWM0_BASE;
-       } else {
-               nPWM = 1;
-               nTimer = timer - 4;
-               PWM_BASE_ADDR = PWM1_BASE;
-       }
-
-       /* Timer info initialization */
-
-       /* Have we already initialized? */
-       if (!pwm_initialized[nPWM]) {
-               /* set prescaler to 1/16, set divider MUX to 1/16 */
-               putreg32(0x0101, PWM_BASE_ADDR + TCFG0);
-               putreg32(0x0000, PWM_BASE_ADDR + TCFG1);
-               putreg32(0, PWM_BASE_ADDR + TCON);
-
-               lower = &g_pwmdev[timer];
-
-               for (i = 0; i < 4; i++) {
-                       tmp = &g_pwmdev[nPWM * 4 + i];
-                       tmp->intdata = &intdata[i];
-                       tmp->id = nPWM * 4 + i;
-                       tmp->irq = (IRQ_PWM0_0) + nPWM * 4 + i;
-
-                       tmp->base = (void *)PWM_BASE_ADDR;
-
-                       tmp->ops = &g_pwmops;
-
-                       /* clock setting or clock information */
-                       /* it should be replaced with cal code. */
-                       tmp->timer_pclk = PWM_PCLK;
+       struct pwm_lowerhalf_s *lower = NULL;
 
-                       tmp->pre_scaler = 2;
-                       tmp->divider = 1;
-
-                       /* set default frenquency : 100hz */
-                       tmp->freq = 100;
-
-                       /* set default duty cycle: 50% */
-                       tmp->dutycycle = 50;
-               }
-
-               /* Now we are initialized */
-               pwm_initialized[nPWM] = true;
-       } else {
-               lower = &g_pwmdev[timer];
-               //frequency
-               lower->freq = lower->timer_pclk / (lower->pre_scaler) / lower->divider;
-       }
-
-       /* There is only 6 IRQ ID (PWM0_0 ~ PWM1_1 */
-       if (timer < TOTAL_NUMBER_OF_PWMOUT) {
-               /* IRQ register */
-               irq_attach(lower->irq, s5j_pwm_timer_interrupt, NULL);
-               up_disable_irq(lower->irq);
-
-               /* IRQ trigger = level */
-               putreg32(0x1, 0x800A0000 + 0x044c);
+#ifdef CONFIG_S5J_PWM0
+       if (timer == 0) {
+               lower = (struct pwm_lowerhalf_s *)&g_pwm0_0;
+       } else
+#endif
+#ifdef CONFIG_S5J_PWM1
+       if (timer == 1) {
+               lower = (struct pwm_lowerhalf_s *)&g_pwm0_1;
+       } else
+#endif
+#ifdef CONFIG_S5J_PWM2
+       if (timer == 2) {
+               lower = (struct pwm_lowerhalf_s *)&g_pwm0_2;
+       } else
+#endif
+#ifdef CONFIG_S5J_PWM3
+       if (timer == 3) {
+               lower = (struct pwm_lowerhalf_s *)&g_pwm0_3;
+       } else
+#endif
+#ifdef CONFIG_S5J_PWM4
+       if (timer == 4) {
+               lower = (struct pwm_lowerhalf_s *)&g_pwm1_0;
+       } else
+#endif
+#ifdef CONFIG_S5J_PWM5
+       if (timer == 5) {
+               lower = (struct pwm_lowerhalf_s *)&g_pwm1_1;
+       } else
+#endif
+       {
+               lldbg("ERROR: invalid PWM is requested\n");
        }
 
-       return (FAR struct pwm_lowerhalf_s *)lower;
+       return lower;
 }
index 4adc5c2..c3017ff 100644 (file)
  * POSSIBILITY OF SUCH DAMAGE.
  *
  */
-/****************************************************************************
- * Included Files
- ****************************************************************************/
 
-#ifndef        __S5J_PWM_H_
-#define        __S5J_PWM_H_
+#ifndef        __ARCH_ARM_SRC_S5J_S5J_PWM_H
+#define        __ARCH_ARM_SRC_S5J_S5J_PWM_H
 
 /****************************************************************************
- * Pre-proessor Definitions
+ * Included Files
  ****************************************************************************/
-#define __SYSCALL_USER_DEF                     (0x10000000)
-
-/* Start user definition ioctl request for timer */
-#define __TIMER_USER_DEF                       (0x10000000)
-//#define PWM_WAIT_INT              (__TIMER_USER_DEF + 0x1)
-#define PWM_SET_PRESCALER                      (__TIMER_USER_DEF + 0x2)
-#define PWM_SET_DIVIDER                                (__TIMER_USER_DEF + 0x3)
-#define PWM_SET_DEADZONE                       (__TIMER_USER_DEF + 0x4)
-#define PWM_SET_TCMP                           (__TIMER_USER_DEF + 0x5)
-//#define PWM_SET_TIME_ORDER            (__TIMER_USER_DEF + 0x6)
-#define PWM_SET_DUTY_CYCLE                     (__TIMER_USER_DEF + 0x7)
-
-#define PWM_START_ENABLE_TOUT                  (__TIMER_USER_DEF + 0x10)
-#define PWM_START_ENABLE_ONETIME                       (__TIMER_USER_DEF + 0x11)
-
-#define PWM_PCLK    (26000000)
-
-#define TREG_INVAL      0xFFFF
-
-#define TCFG0           0x0000
-#define TCFG1           0x0004
-#define TCON            0x0008
-
-#define TCNTB(x)        (0x000C + x * 0xC)
-#define TCMPB(x)        (x < 4 ? (0x0010 + x * 0xC) : TREG_INVAL)
-#define TCNTO(x)        (x < 4 ? (0x0014 + x * 0xC) : 0x0040)
-
-#define TINT_CSTAT      0x0044
-
-#define TIMER_PREDIVID  256
+#include <tinyara/config.h>
 
-#define TIME_NS     1
-#define TIME_MS     0
+#include <tinyara/pwm.h>
 
-#define TIMER_SRC_PCLK  0
-#define TIMER_SRC_SCLK  1
-
-#define MAX_NO_PWM      4
-#define TOTAL_NUMBER_OF_TIMER      8
-#define TOTAL_NUMBER_OF_PWMOUT      6
+#ifdef CONFIG_S5J_S5JT200
+#include "chip/s5jt200_pwm.h"
+#else
+#error "S5J chip is not specified"
+#endif
 
 /****************************************************************************
- * Private Types
+ * Public Functions
  ****************************************************************************/
-
-/* sfr offset */
-struct s5j_pwm_intdata {
-       int pwm_no;
-       int64_t int_count;
-       int32_t reload;
-       int32_t manual_update;
-       int32_t start;
-       int32_t invert;
-       int32_t prescaler;
-       int32_t div_mux;
-};
-
-/* This structure represents the state of one PWM timer */
-struct s5j_pwmtimer_s {
-       FAR const struct pwm_ops_s *ops;        /* PWM operations */
-
-       int id;
-       void *base;
-       int irq;
-
-       /* Add private data structures if it is needed */
-       unsigned long long timer_pclk;          /* input clock Hz */
-       int pre_scaler;
-       int divider;
-       int freq;
-       int dutycycle;                          //0~100
-       void *callback;
-
-       struct s5j_pwm_intdata *intdata;
-};
-
-static int s5j_pwm_interrupt(struct s5j_pwmtimer_s *priv);
-static int s5j_pwm_timer_interrupt(int irq, void *context, void *arg);
-static int s5j_pwm_setup(FAR struct pwm_lowerhalf_s *dev);
-static int s5j_pwm_shutdown(FAR struct pwm_lowerhalf_s *dev);
-#ifdef CONFIG_PWM_PULSECOUNT
-static int s5j_pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info, FAR void *handle);
-#else
-static int s5j_pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info);
-#endif
-static int s5j_pwm_stop(FAR struct pwm_lowerhalf_s *dev);
-static int s5j_pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg);
-static int s5j_pwm_set_frequency_dutycycle(FAR struct pwm_lowerhalf_s *dev, int32_t frequency, int32_t duty);
 FAR struct pwm_lowerhalf_s *s5j_pwminitialize(int timer);
 
-#endif
+#endif /* __ARCH_ARM_SRC_S5J_S5J_PWM_H */