From 114f132c51e047c845f94908bb6e7607c02f1252 Mon Sep 17 00:00:00 2001 From: Bongryul Lee Date: Thu, 20 Apr 2017 20:56:46 +0900 Subject: [PATCH] s5j/pwm: rework pwm lower-half driver 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 --- apps/examples/sensorbd_demo/Kconfig | 7 +- apps/examples/sensorbd_demo/examples/pwm_buzzer.c | 4 +- apps/examples/sensorbd_demo/examples/pwm_led.c | 4 +- build/configs/artik053/extra/defconfig | 13 +- build/configs/artik053/minimal/defconfig | 7 +- build/configs/artik053/nettest/defconfig | 12 + build/configs/artik053/typical/defconfig | 13 +- build/configs/sidk_s5jt200/hello/defconfig | 6 + .../configs/sidk_s5jt200/hello_with_tash/defconfig | 6 + build/configs/sidk_s5jt200/kernel_sample/defconfig | 6 + .../configs/sidk_s5jt200/sidk_tash_wlan/defconfig | 12 + build/configs/sidk_s5jt200/tc/defconfig | 12 + framework/src/iotbus/iotbus_pwm.c | 2 +- os/arch/arm/src/s5j/Kconfig | 68 +- os/arch/arm/src/s5j/chip/s5j_memorymap.h | 4 +- os/arch/arm/src/s5j/chip/s5jt200_pwm.h | 307 +++++++++ os/arch/arm/src/s5j/s5j_pwm.c | 697 ++++++--------------- os/arch/arm/src/s5j/s5j_pwm.h | 102 +-- 18 files changed, 671 insertions(+), 611 deletions(-) create mode 100644 os/arch/arm/src/s5j/chip/s5jt200_pwm.h diff --git a/apps/examples/sensorbd_demo/Kconfig b/apps/examples/sensorbd_demo/Kconfig index 1521a24..dea474c 100644 --- a/apps/examples/sensorbd_demo/Kconfig +++ b/apps/examples/sensorbd_demo/Kconfig @@ -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 diff --git a/apps/examples/sensorbd_demo/examples/pwm_buzzer.c b/apps/examples/sensorbd_demo/examples/pwm_buzzer.c index 490bc37..b443881 100644 --- a/apps/examples/sensorbd_demo/examples/pwm_buzzer.c +++ b/apps/examples/sensorbd_demo/examples/pwm_buzzer.c @@ -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); diff --git a/apps/examples/sensorbd_demo/examples/pwm_led.c b/apps/examples/sensorbd_demo/examples/pwm_led.c index 3d1cfc3..a49b75c 100644 --- a/apps/examples/sensorbd_demo/examples/pwm_led.c +++ b/apps/examples/sensorbd_demo/examples/pwm_led.c @@ -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); diff --git a/build/configs/artik053/extra/defconfig b/build/configs/artik053/extra/defconfig index 44cd9e8..0db35a4 100644 --- a/build/configs/artik053/extra/defconfig +++ b/build/configs/artik053/extra/defconfig @@ -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 diff --git a/build/configs/artik053/minimal/defconfig b/build/configs/artik053/minimal/defconfig index 7735d01..84205cf 100644 --- a/build/configs/artik053/minimal/defconfig +++ b/build/configs/artik053/minimal/defconfig @@ -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 diff --git a/build/configs/artik053/nettest/defconfig b/build/configs/artik053/nettest/defconfig index 322b1d5..6b3d43d 100644 --- a/build/configs/artik053/nettest/defconfig +++ b/build/configs/artik053/nettest/defconfig @@ -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 # diff --git a/build/configs/artik053/typical/defconfig b/build/configs/artik053/typical/defconfig index f42f753..6784582 100644 --- a/build/configs/artik053/typical/defconfig +++ b/build/configs/artik053/typical/defconfig @@ -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 diff --git a/build/configs/sidk_s5jt200/hello/defconfig b/build/configs/sidk_s5jt200/hello/defconfig index 680f2dc..e91a15f 100644 --- a/build/configs/sidk_s5jt200/hello/defconfig +++ b/build/configs/sidk_s5jt200/hello/defconfig @@ -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 diff --git a/build/configs/sidk_s5jt200/hello_with_tash/defconfig b/build/configs/sidk_s5jt200/hello_with_tash/defconfig index 9392c64..a1f6f0a 100644 --- a/build/configs/sidk_s5jt200/hello_with_tash/defconfig +++ b/build/configs/sidk_s5jt200/hello_with_tash/defconfig @@ -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 diff --git a/build/configs/sidk_s5jt200/kernel_sample/defconfig b/build/configs/sidk_s5jt200/kernel_sample/defconfig index 2dd126d..ed75f76 100644 --- a/build/configs/sidk_s5jt200/kernel_sample/defconfig +++ b/build/configs/sidk_s5jt200/kernel_sample/defconfig @@ -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 diff --git a/build/configs/sidk_s5jt200/sidk_tash_wlan/defconfig b/build/configs/sidk_s5jt200/sidk_tash_wlan/defconfig index aa9355f..9401400 100644 --- a/build/configs/sidk_s5jt200/sidk_tash_wlan/defconfig +++ b/build/configs/sidk_s5jt200/sidk_tash_wlan/defconfig @@ -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 # diff --git a/build/configs/sidk_s5jt200/tc/defconfig b/build/configs/sidk_s5jt200/tc/defconfig index 52e1f6f..d310356 100644 --- a/build/configs/sidk_s5jt200/tc/defconfig +++ b/build/configs/sidk_s5jt200/tc/defconfig @@ -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 # diff --git a/framework/src/iotbus/iotbus_pwm.c b/framework/src/iotbus/iotbus_pwm.c index e4a7d4d..248bcfd 100644 --- a/framework/src/iotbus/iotbus_pwm.c +++ b/framework/src/iotbus/iotbus_pwm.c @@ -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); diff --git a/os/arch/arm/src/s5j/Kconfig b/os/arch/arm/src/s5j/Kconfig index bd53a63..b33f778 100644 --- a/os/arch/arm/src/s5j/Kconfig +++ b/os/arch/arm/src/s5j/Kconfig @@ -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 diff --git a/os/arch/arm/src/s5j/chip/s5j_memorymap.h b/os/arch/arm/src/s5j/chip/s5j_memorymap.h index f9c481f..cd6d966 100644 --- a/os/arch/arm/src/s5j/chip/s5j_memorymap.h +++ b/os/arch/arm/src/s5j/chip/s5j_memorymap.h @@ -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 index 0000000..fca2a2d --- /dev/null +++ b/os/arch/arm/src/s5j/chip/s5jt200_pwm.h @@ -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 + * + * 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 */ diff --git a/os/arch/arm/src/s5j/s5j_pwm.c b/os/arch/arm/src/s5j/s5j_pwm.c index d337446..8b1c388 100644 --- a/os/arch/arm/src/s5j/s5j_pwm.c +++ b/os/arch/arm/src/s5j/s5j_pwm.c @@ -18,14 +18,8 @@ /**************************************************************************** * arch/arm/src/s5j/s5j_pwm.c * - * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * 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 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -55,153 +49,83 @@ * POSSIBILITY OF SUCH DAMAGE. * */ + /**************************************************************************** * Included Files ****************************************************************************/ #include #include -#include -#include -#include -#include -#include +#include #include -#include +#include -#include +#include -#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; } diff --git a/os/arch/arm/src/s5j/s5j_pwm.h b/os/arch/arm/src/s5j/s5j_pwm.h index 4adc5c2..c3017ff 100644 --- a/os/arch/arm/src/s5j/s5j_pwm.h +++ b/os/arch/arm/src/s5j/s5j_pwm.h @@ -55,104 +55,26 @@ * 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 -#define TIME_NS 1 -#define TIME_MS 0 +#include -#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 */ -- 2.7.4