s5j/pwm: rework pwm driver
authorJihoon Park <jh6186.park@samsung.com>
Fri, 31 Mar 2017 11:36:15 +0000 (20:36 +0900)
committerHeesub Shin <heesub.shin@samsung.com>
Tue, 18 Apr 2017 03:02:04 +0000 (12:02 +0900)
fix prefix for s5j, functions are named as s5j_pwm_xxx. SFR access uses
getreg/putreg. sidk_s5jt200 board initializes pwm channels accordingly
for board definition. It has 6 PWM output and 3 s8300 driver exsited on
sidk s5jt200 evaludation board.

pwm functions except s5j_pwminitialize names with staic and not appears
lower half and upper half.

FAR struct pwm_lowerhalf_s *foo;
foo->ops->start() is allowed to access PWM functionalities.

Change-Id: I120284b114f9994ec96e100809975b0e17823fa7
Signed-off-by: Heesub Shin <heesub.shin@samsung.com>
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
os/arch/arm/src/s5j/s5j_pwm.c
os/arch/arm/src/s5j/s5j_pwm.h
os/arch/arm/src/sidk_s5jt200/Kconfig
os/arch/arm/src/sidk_s5jt200/src/Makefile
os/arch/arm/src/sidk_s5jt200/src/s5jt200_boot.c
os/arch/arm/src/sidk_s5jt200/src/s5jt200_pwm.c [new file with mode: 0644]
os/arch/arm/src/sidk_s5jt200/src/s5jt200_tash.c

index bd5dc74..deccdf4 100644 (file)
@@ -304,6 +304,7 @@ CONFIG_ARCH_HAVE_IRQBUTTONS=y
 #
 # Board-Specific Options
 #
+CONFIG_SIDK_S5JT200_PWM_CHNUM=6
 CONFIG_SIDK_S5JT200_FLASH_CAPACITY=8388608
 CONFIG_SIDK_S5JT200_FLASH_PAGE_SIZE=4096
 CONFIG_SIDK_S5JT200_FLASH_MINOR=0
index 706ce2f..23e915a 100644 (file)
@@ -305,6 +305,7 @@ CONFIG_BOARD_RAMDUMP_UART=y
 #
 # Board-Specific Options
 #
+CONFIG_SIDK_S5JT200_PWM_CHNUM=6
 CONFIG_SIDK_S5JT200_FLASH_CAPACITY=8388608
 CONFIG_SIDK_S5JT200_FLASH_PAGE_SIZE=4096
 CONFIG_SIDK_S5JT200_FLASH_MINOR=0
index aceca71..ed0b798 100755 (executable)
@@ -309,6 +309,7 @@ CONFIG_ARCH_HAVE_IRQBUTTONS=y
 #
 # Board-Specific Options
 #
+CONFIG_SIDK_S5JT200_PWM_CHNUM=6
 CONFIG_SIDK_S5JT200_FLASH_CAPACITY=8388608
 CONFIG_SIDK_S5JT200_FLASH_PAGE_SIZE=4096
 CONFIG_SIDK_S5JT200_FLASH_MINOR=0
index 6451ff0..232ec63 100644 (file)
@@ -305,6 +305,7 @@ CONFIG_BOARD_RAMDUMP_UART=y
 #
 # Board-Specific Options
 #
+CONFIG_SIDK_S5JT200_PWM_CHNUM=6
 CONFIG_SIDK_S5JT200_FLASH_CAPACITY=8388608
 CONFIG_SIDK_S5JT200_FLASH_PAGE_SIZE=4096
 CONFIG_SIDK_S5JT200_FLASH_MINOR=0
index 1c7d242..31c0898 100644 (file)
  * POSSIBILITY OF SUCH DAMAGE.
  *
  */
-
 /****************************************************************************
  * Included Files
  ****************************************************************************/
-
 #include <tinyara/config.h>
 
 #include <sys/types.h>
 #include "s5j_pwm.h"
 
 /****************************************************************************
- * Pre-proessor Definitions
- ****************************************************************************/
-#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
-
-#define TIME_NS         1
-#define TIME_MS         0
-
-#define TIMER_SRC_PCLK  0
-#define TIMER_SRC_SCLK  1
-
-#define MAX_NO_PWM      5
-#define TOTAL_NUMBER_OF_TIMER      10
-
-/****************************************************************************
- * Private Types
- ****************************************************************************/
-
-/* sfr offset */
-struct 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 */
-       cycle_t timer_pclk;                     /* input clock Hz */
-       int pre_scaler;
-       int divider;
-       int freq;
-       int dutycycle;                          //0~100
-       void *callback;
-
-       struct pwm_intdata *intdata;
-};
-
-/****************************************************************************
  * Static Function Prototypes
  ****************************************************************************/
-/* Register access */
-
-static uint32_t pwm_getreg(struct s5j_pwmtimer_s *priv, int offset);
-static void pwm_putreg(struct s5j_pwmtimer_s *priv, int offset, uint32_t value);
-
-static void pwm_dumpregs(struct s5j_pwmtimer_s *priv, FAR const char *msg);
-
-/* Timer management */
-static int pwm_interrupt(struct s5j_pwmtimer_s *priv);
-static int pwm_timer_interrupt(int irq, void *context);
-
-/* PWM driver methods */
-
-static int pwm_setup(FAR struct pwm_lowerhalf_s *dev);
-static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev);
-
-#ifdef CONFIG_PWM_PULSECOUNT
-static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info, FAR void *handle);
-#else
-static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info);
-#endif
-
-static int pwm_stop(FAR struct pwm_lowerhalf_s *dev);
-static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg);
-
-static int pwm_set_frequency_dutycycle(FAR struct pwm_lowerhalf_s *dev, int32_t frequency, int32_t duty);
-
-static FAR struct pwm_lowerhalf_s *s5j_pwminitialize(int timer);
-
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -180,11 +88,11 @@ static FAR struct pwm_lowerhalf_s *s5j_pwminitialize(int timer);
 static bool pwm_initialized[2] = { false, false };
 
 static const struct pwm_ops_s g_pwmops = {
-       .setup = pwm_setup,
-       .shutdown = pwm_shutdown,
-       .start = pwm_start,
-       .stop = pwm_stop,
-       .ioctl = pwm_ioctl,
+       .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];
@@ -192,7 +100,7 @@ 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 pwm_intdata intdata[MAX_NO_PWM] = {
+struct s5j_pwm_intdata intdata[MAX_NO_PWM] = {
        {
                .pwm_no = 0,
                .int_count = 0,
@@ -222,7 +130,8 @@ struct pwm_intdata intdata[MAX_NO_PWM] = {
                .invert = (1 << 14),
                .prescaler = 8,
                .div_mux = 8,
-       }, {
+       },
+       {
                .pwm_no = 3,
                .int_count = 0,
                .reload = (1 << 19),
@@ -232,16 +141,6 @@ struct pwm_intdata intdata[MAX_NO_PWM] = {
                .prescaler = 8,
                .div_mux = 12,
        },
-       {
-               .pwm_no = 4,
-               .int_count = 0,
-               .reload = (1 << 22),
-               .manual_update = (1 << 21),
-               .start = (1 << 20),
-               .invert = TREG_INVAL,
-               .prescaler = 8,
-               .div_mux = 16,
-       },
 };
 
 /****************************************************************************
@@ -249,7 +148,7 @@ struct pwm_intdata intdata[MAX_NO_PWM] = {
  ****************************************************************************/
 
 /****************************************************************************
- * Name: pwm_interrupt
+ * Name: s5j_pwm_interrupt
  *
  * Description:
  *   Handle timer interrupts.
@@ -261,14 +160,13 @@ struct pwm_intdata intdata[MAX_NO_PWM] = {
  *   Zero on success; a negated errno value on failure
  *
  ****************************************************************************/
-static int pwm_interrupt(struct s5j_pwmtimer_s *priv)
+static int s5j_pwm_interrupt(struct s5j_pwmtimer_s *priv)
 {
-       /* TODO pwm_interrupt */
        return 0;
 }
 
 /****************************************************************************
- * Name: pwm_timer_interrupt
+ * Name: s5j_pwm_timer_interrupt
  *
  * Description:
  *   Handle pwm 0..4 interrupts.
@@ -280,25 +178,33 @@ static int pwm_interrupt(struct s5j_pwmtimer_s *priv)
  *   Zero on success; a negated errno value on failure
  *
  ****************************************************************************/
-static int pwm_timer_interrupt(int irq, void *context)
+static int s5j_pwm_timer_interrupt(int irq, void *context)
 {
-       int32_t pwm_no;
-       int32_t int_stat;
+       signed int pwm_no;
+       signed int irq_no;
+       signed int int_stat;
        FAR struct s5j_pwmtimer_s *priv;
 
-       pwm_no = irq - IRQ_PWM0_0;
+       irq_no = irq - IRQ_PWM0_0;
+
+       if (irq_no > 4) {
+               pwm_no = irq_no - 1;
+       } else {
+               pwm_no = irq_no;
+       }
+
        priv = &g_pwmdev[pwm_no];
 
        /* Clear interrupt pending register */
-       int_stat = __raw_readl(priv->base + TINT_CSTAT) & 0x1F;
-       int_stat |= (1 << (5 + pwm_no));
-       __raw_writel(int_stat, priv->base + TINT_CSTAT);
+       int_stat = getreg32(priv->base + TINT_CSTAT) & 0x1F;
+       int_stat |= (1 << (5 + irq_no));
+       putreg32(int_stat, priv->base + TINT_CSTAT);
 
-       return pwm_interrupt(priv);
+       return s5j_pwm_interrupt(priv);
 }
 
 /****************************************************************************
- * Name: pwm_setup
+ * Name: s5j_pwm_setup
  *
  * Description:
  *   This method is called when the driver is opened.  The lower half driver
@@ -317,36 +223,32 @@ static int pwm_timer_interrupt(int irq, void *context)
  *
  ****************************************************************************/
 
-static int pwm_setup(FAR struct pwm_lowerhalf_s *dev)
+static int s5j_pwm_setup(FAR struct pwm_lowerhalf_s *dev)
 {
        FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       //struct pwm_intdata *pwm_data = priv->intdata;
 
        int gpio_TOUT;
+       int channel;
 
-       lldbg("pwm setup\n");
+       channel = priv->id;
 
+       //skip channel4
+       if (channel >= 4) {
+               channel += 1;
+       }
        // T20 has the output port(TOUT0~6).
-       if (priv->id < 7) {
-               gpio_TOUT = s5j_gpio(GPP2, (priv->id));
+       if (channel < 7) {
+               gpio_TOUT = s5j_gpio(GPP2, (channel));
 
                gpio_cfg_pin(gpio_TOUT, GPIO_FUNC(2));
                gpio_set_pull(gpio_TOUT, GPIO_PULL_NONE);
        }
-       //This code enables "XGPIO27" to enable Buzz power. It should be removed because of specific board configuration.
-       gpio_TOUT = s5j_gpio(GPG3, 3);
-       gpio_cfg_pin(gpio_TOUT, GPIO_FUNC(1));
-       gpio_set_pull(gpio_TOUT, GPIO_PULL_NONE);
-       gpio_set_value(gpio_TOUT, 1);
-
-       //__raw_writel(0x0F0F, priv->base + TCFG0);
-       //__raw_writel(0x44444, priv->base + TCFG1);
 
        return OK;
 }
 
 /****************************************************************************
- * Name: pwm_shutdown
+ * Name: s5j_pwm_shutdown
  *
  * Description:
  *   This method is called when the driver is closed.  The lower half driver
@@ -361,31 +263,35 @@ static int pwm_setup(FAR struct pwm_lowerhalf_s *dev)
  *
  ****************************************************************************/
 
-static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
+static int s5j_pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
 {
        FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       //struct pwm_intdata *pwm_data = priv->intdata;
 
        int gpio_TOUT;
+       int channel;
 
-       lldbg("pwm shutdown\n");
+       channel = priv->id;
 
+       //skip channel4
+       if (channel >= 4) {
+               channel += 1;
+       }
        // GPIO input mode, pull-down
-       if (priv->id < 7) {
-               gpio_TOUT = s5j_gpio(GPP2, (priv->id));
+       if (channel < 7) {
+               gpio_TOUT = s5j_gpio(GPP2, channel);
 
                gpio_cfg_pin(gpio_TOUT, GPIO_FUNC(0));
                gpio_set_pull(gpio_TOUT, GPIO_PULL_DOWN);
        }
 
        /* Make sure that the output has been stopped */
-       pwm_stop(dev);
+       s5j_pwm_stop(dev);
 
        return OK;
 }
 
 /****************************************************************************
- * Name: pwm_start
+ * Name: s5j_pwm_start
  *
  * Description:
  *   (Re-)initialize the timer resources and start the pulsed output
@@ -399,54 +305,51 @@ static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
  *
  ****************************************************************************/
 #ifdef CONFIG_PWM_PULSECOUNT
-static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info, FAR void *handle)
+static int s5j_pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info, FAR void *handle)
 #else
-static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info)
+static int s5j_pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info)
 #endif
 {
        FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       struct pwm_intdata *pwm_data = priv->intdata;
-
-       //unsigned long flag;
-       int32_t tcon;
-       int32_t int_stat;
-
-       lldbg("pwm start\n");
+       struct s5j_pwm_intdata *pwm_data = priv->intdata;
 
+       signed int tcon, int_stat;
 #ifdef CONFIG_PWM_PULSECOUNT
        priv->callback = handle;
 #endif
 
-       pwm_set_frequency_dutycycle(dev, info->frequency, info->duty);
+       s5j_pwm_set_frequency_dutycycle(dev, info->frequency, info->duty);
 
        /* Enable interrupt */
-       int_stat = __raw_readl(priv->base + TINT_CSTAT) & 0x1F;
+       int_stat = getreg32(priv->base + TINT_CSTAT) & 0x1F;
        int_stat |= (1 << priv->id);
-       __raw_writel(int_stat, priv->base + TINT_CSTAT);
+       putreg32(int_stat, priv->base + TINT_CSTAT);
 
-       tcon = __raw_readl(priv->base + TCON);
+       tcon = getreg32(priv->base + TCON);
 
        /* interrupt enable */
        //up_enable_irq(priv->irq);
+
        /* Manual update */
-       __raw_writel(tcon | pwm_data->manual_update, priv->base + TCON);
+       putreg32(tcon | pwm_data->manual_update, priv->base + TCON);
 
 #if 0
        if (type == TIMER_TYPE_ONE_SHOT) {      /* ONESHOT */
                tcon &= ~(pwm_data->reload);
        } else                                          /* INTERVAL */
 #endif
+
                tcon |= pwm_data->reload;
 
        tcon |= pwm_data->start;
 
-       __raw_writel(tcon, priv->base + TCON);
+       putreg32(tcon, priv->base + TCON);
 
        return 0;
 }
 
 /****************************************************************************
- * Name: pwm_stop
+ * Name: s5j_pwm_stop
  *
  * Description:
  *   Stop the pulsed output and reset the timer resources
@@ -464,27 +367,23 @@ static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_
  *
  ****************************************************************************/
 
-static int pwm_stop(FAR struct pwm_lowerhalf_s *dev)
+static int s5j_pwm_stop(FAR struct pwm_lowerhalf_s *dev)
 {
        FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       struct pwm_intdata *pwm_data = priv->intdata;
-
-       //unsigned long flag;
-       int32_t tcon;
-       int32_t int_stat;
+       struct s5j_pwm_intdata *pwm_data = priv->intdata;
 
-       lldbg("pwm stop\n");
+       signed int tcon, int_stat;
 
        /* Disable interrupt */
-       int_stat = __raw_readl(priv->base + TINT_CSTAT) & 0x1F;
+       int_stat = getreg32(priv->base + TINT_CSTAT) & 0x1F;
        int_stat &= ~(1 << pwm_data->pwm_no);
-       __raw_writel(int_stat, priv->base + TINT_CSTAT);
+       putreg32(int_stat, priv->base + TINT_CSTAT);
 
-       tcon = __raw_readl(priv->base + TCON);
+       tcon = getreg32(priv->base + TCON);
        tcon &= ~pwm_data->start;
        tcon &= ~pwm_data->reload;
        tcon &= ~pwm_data->invert;
-       __raw_writel(tcon, priv->base + TCON);
+       putreg32(tcon, priv->base + TCON);
 
        /* interrupt disable */
        up_disable_irq(priv->irq);
@@ -494,13 +393,13 @@ static int pwm_stop(FAR struct pwm_lowerhalf_s *dev)
        return 0;
 }
 
-static int pwm_set_dutycycle(FAR struct pwm_lowerhalf_s *dev, int32_t duty)
+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 pwm_intdata *pwm_data = priv->intdata;
-       int32_t tcntb;
-       int32_t tcmpb;
-       int32_t id;
+       struct s5j_pwm_intdata *pwm_data = priv->intdata;
+       signed int tcntb;
+       signed int tcmpb;
+       signed int id;
        int64_t tmp;
 
        if (duty > 100) {
@@ -510,28 +409,24 @@ static int pwm_set_dutycycle(FAR struct pwm_lowerhalf_s *dev, int32_t duty)
        priv->dutycycle = duty;
        id = pwm_data->pwm_no;
 
-       tcntb = __raw_readl(priv->base + TCNTB(id));
+       tcntb = getreg32(priv->base + TCNTB(id));
 
        tmp = ((tcntb + 1) * duty) / 100 - 1;   // duty range :0 ~ 100
-       tcmpb = (int32_t)tmp;
+       tcmpb = (signed int)tmp;
 
-       if (priv->id == 4 || priv->id == 9) {
-               //There is no TBMPB register for Timer4,9
-       } else {
-               __raw_writel(tcmpb, priv->base + TCMPB(id));
-       }
+       putreg32(tcmpb, priv->base + TCMPB(id));
 
        return 0;
 }
 
-static int pwm_set_pulsewidth(FAR struct pwm_lowerhalf_s *dev, int32_t frequency)
+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 pwm_intdata *pwm_data = priv->intdata;
-       int32_t tcntb;
-       int32_t id;
+       struct s5j_pwm_intdata *pwm_data = priv->intdata;
+       signed int tcntb;
+       signed int id;
 
-       int32_t timerclockfreq;
+       signed int timerclockfreq;
 
        timerclockfreq = PWM_PCLK / priv->pre_scaler / priv->divider;
        if ((timerclockfreq / 2) < frequency) {
@@ -542,38 +437,37 @@ static int pwm_set_pulsewidth(FAR struct pwm_lowerhalf_s *dev, int32_t frequency
        priv->freq = frequency;
        id = pwm_data->pwm_no;
 
-       tcntb = (priv->timer_pclk / priv->pre_scaler / priv->divider / frequency)
-                       - 1;
-       __raw_writel(tcntb, priv->base + TCNTB(id));
+       tcntb = (priv->timer_pclk / priv->pre_scaler / priv->divider / frequency) - 1;
+       putreg32(tcntb, priv->base + TCNTB(id));
 
        return 0;
 }
 
-static int pwm_set_frequency_dutycycle(FAR struct pwm_lowerhalf_s *dev, int32_t frequency, int32_t duty)
+static int s5j_pwm_set_frequency_dutycycle(FAR struct pwm_lowerhalf_s *dev, signed int frequency, signed int duty)
 {
-       pwm_set_pulsewidth(dev, frequency);
-       pwm_set_dutycycle(dev, duty);
+       s5j_pwm_set_pulsewidth(dev, frequency);
+       s5j_pwm_set_dutycycle(dev, duty);
 
        return 0;
 }
 
 /* scaler_val : 1 ~ 256 */
-static int pwm_set_prescaler(FAR struct pwm_lowerhalf_s *dev, int32_t scaler_val)
+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 pwm_intdata *pwm_data = priv->intdata;
+       struct s5j_pwm_intdata *pwm_data = priv->intdata;
 
        int i;
-       int32_t id;
-       int32_t tcntb;
-       int32_t val;
-       int32_t nPWM;
+       signed int id;
+       signed int tcntb;
+       signed int val;
+       signed int nPWM;
        //unsigned long flag;
 
-       if (priv->id < 5) {
+       if (priv->id < 4) {
                nPWM = 0;
        } else {
-               nPWM = 5;
+               nPWM = 4;
        }
 
        if (pwm_data->pwm_no < 2) {
@@ -582,45 +476,40 @@ static int pwm_set_prescaler(FAR struct pwm_lowerhalf_s *dev, int32_t scaler_val
 
                        pwm_data = priv->intdata;
 
-                       if ((__raw_readl(priv->base + TCON)
-                                & (g_pwmdev[nPWM + i].intdata->start)) != 0) {
+                       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;
-                               __raw_writel(tcntb, g_pwmdev[nPWM + i].base + TCNTB(id));
+                               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 < 5; i++) {
+               for (i = 2; i < 4; i++) {
                        g_pwmdev[nPWM + i].pre_scaler = scaler_val;
 
-                       if ((__raw_readl(priv->base + TCON)
-                                & (g_pwmdev[nPWM + i].intdata->start)) != 0) {
+                       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;
-                               __raw_writel(tcntb, g_pwmdev[nPWM + i].base + TCNTB(id));
+                               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 = __raw_readl(priv->base + TCFG0);
+       val = getreg32(priv->base + TCFG0);
        val &= ~(0xFF << pwm_data->prescaler);
        val |= ((scaler_val - 1) << pwm_data->prescaler);
-       __raw_writel(val, priv->base + TCFG0);
+       putreg32(val, priv->base + TCFG0);
 
        return 0;
 }
 
 /* scaler_val : 0 ~ 4 */
-static int pwm_set_divider(FAR struct pwm_lowerhalf_s *dev, int32_t div_val)
+static int s5j_pwm_set_divider(FAR struct pwm_lowerhalf_s *dev, signed int div_val)
 {
        FAR struct s5j_pwmtimer_s *priv = (FAR struct s5j_pwmtimer_s *)dev;
-       struct pwm_intdata *pwm_data = priv->intdata;
-       //unsigned long flag;
-       int32_t val;
+       struct s5j_pwm_intdata *pwm_data = priv->intdata;
+       signed int val;
 
        switch (div_val) {
        case 0: {
@@ -647,19 +536,19 @@ static int pwm_set_divider(FAR struct pwm_lowerhalf_s *dev, int32_t div_val)
                return -EINVAL;
        }
 
-       val = __raw_readl(priv->base + TCFG1);
+       val = getreg32(priv->base + TCFG1);
        val &= ~(0xF << pwm_data->div_mux);
        val |= (div_val << pwm_data->div_mux);
-       __raw_writel(val, priv->base + TCFG1);
+       putreg32(val, priv->base + TCFG1);
 
-       pwm_set_pulsewidth(dev, priv->freq);
-       pwm_set_dutycycle(dev, priv->dutycycle);
+       s5j_pwm_set_pulsewidth(dev, priv->freq);
+       s5j_pwm_set_dutycycle(dev, priv->dutycycle);
 
        return 0;
 }
 
 /****************************************************************************
- * Name: pwm_ioctl
+ * Name: s5j_pwm_ioctl
  *
  * Description:
  *   Lower-half logic may support platform-specific ioctl commands
@@ -674,46 +563,42 @@ static int pwm_set_divider(FAR struct pwm_lowerhalf_s *dev, int32_t div_val)
  *
  ****************************************************************************/
 
-static int 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;
-       int32_t val;
-       int32_t tcfg0;
-       //unsigned long flag;
-
-       val = (int32_t)arg;
+       signed int val, tcfg0;
 
-       lldbg("pwm ioctl: cmd: 0x%x arg:0x%x\n", arg);
+       val = (signed int)arg;
 
        switch (cmd) {
        case PWM_SET_PRESCALER: {
-               return pwm_set_prescaler(dev, val);
+               return s5j_pwm_set_prescaler(dev, val);
        }
 
        case PWM_SET_DIVIDER: {
-               return pwm_set_divider(dev, val);
+               return s5j_pwm_set_divider(dev, val);
        }
 
        case PWM_SET_DEADZONE: {
                if (val >= 256) {
                        val = 255;
                }
-               tcfg0 = __raw_readl(priv->base + TCFG0);
+               tcfg0 = getreg32(priv->base + TCFG0);
                tcfg0 &= ~(0xFF << 16);
                tcfg0 |= (val << 16);
-               __raw_writel(tcfg0, priv->base + TCFG0);
+               putreg32(tcfg0, priv->base + TCFG0);
        }
        break;
 
        case PWM_SET_TCMP: {
                if (TCMPB(priv->id) != TREG_INVAL) {
-                       __raw_writel(val, priv->base + TCMPB(priv->id));
+                       putreg32(val, priv->base + TCMPB(priv->id));
                }
        }
        break;
 
        case PWM_SET_DUTY_CYCLE: {
-               pwm_set_dutycycle(dev, val);
+               s5j_pwm_set_dutycycle(dev, val);
        }
        break;
 
@@ -742,25 +627,22 @@ static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg
  *   NULL is returned on any failure.
  *
  ****************************************************************************/
-static FAR struct pwm_lowerhalf_s *s5j_pwminitialize(int timer)
+FAR struct pwm_lowerhalf_s *s5j_pwminitialize(int timer)
 {
-       FAR struct s5j_pwmtimer_s *lower;
-       FAR struct s5j_pwmtimer_s *tmp;
+       struct s5j_pwmtimer_s *lower, *tmp;
 
-       int32_t i;
-       int32_t nPWM;
-       int32_t nTimer;
-       uint32_t PWM_BASE_ADDR;
+       unsigned int i;
+       unsigned int nPWM;
+       unsigned int nTimer;
+       unsigned int PWM_BASE_ADDR;
 
-       /*  lldbg("s5j_pwminitialize\n"); */
-
-       if (timer < 5) {
+       if (timer < 4) {
                nPWM = 0;
                nTimer = timer;
                PWM_BASE_ADDR = PWM0_BASE;
        } else {
                nPWM = 1;
-               nTimer = timer - 5;
+               nTimer = timer - 4;
                PWM_BASE_ADDR = PWM1_BASE;
        }
 
@@ -769,17 +651,17 @@ static FAR struct pwm_lowerhalf_s *s5j_pwminitialize(int timer)
        /* Have we already initialized? */
        if (!pwm_initialized[nPWM]) {
                /* set prescaler to 1/16, set divider MUX to 1/16 */
-               __raw_writel(0x0101, PWM_BASE_ADDR + TCFG0);
-               __raw_writel(0x0000, PWM_BASE_ADDR + TCFG1);
-               __raw_writel(0, PWM_BASE_ADDR + TCON);
+               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 < 5; i++) {
-                       tmp = &g_pwmdev[nPWM * 5 + i];
+               for (i = 0; i < 4; i++) {
+                       tmp = &g_pwmdev[nPWM * 4 + i];
                        tmp->intdata = &intdata[i];
-                       tmp->id = nPWM * 5 + i;
-                       tmp->irq = (IRQ_PWM0_0) + nPWM * 5 + i;
+                       tmp->id = nPWM * 4 + i;
+                       tmp->irq = (IRQ_PWM0_0) + nPWM * 4 + i;
 
                        tmp->base = (void *)PWM_BASE_ADDR;
 
@@ -808,86 +690,14 @@ static FAR struct pwm_lowerhalf_s *s5j_pwminitialize(int timer)
        }
 
        /* There is only 6 IRQ ID (PWM0_0 ~ PWM1_1 */
-       if (timer < 7) {
+       if (timer < TOTAL_NUMBER_OF_PWMOUT) {
                /* IRQ register */
-               irq_attach(lower->irq, pwm_timer_interrupt);
+               irq_attach(lower->irq, s5j_pwm_timer_interrupt);
                up_disable_irq(lower->irq);
 
                /* IRQ trigger = level */
-               __raw_writel(0x1, 0x800A0000 + 0x044c);
+               putreg32(0x1, 0x800A0000 + 0x044c);
        }
 
        return (FAR struct pwm_lowerhalf_s *)lower;
 }
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/**
- *
- * @brief    pwm driver register (/dev/pwm0)
- * @param    void
- * @return   void
- * @note     note here
- */
-void pwmdrv_register(void)
-{
-       struct pwm_lowerhalf_s *pwm;
-       int ret;
-       int ch;
-       char devicename[10];
-
-       for (ch = 0; ch < 10; ch++) {
-
-               /* Call s5j_pwminitialize() to get an instance of the PWM interface */
-               pwm = s5j_pwminitialize(ch);
-               if (!pwm) {
-                       dbg("Failed to get the S5J PWM lower half\n");
-                       return;
-               }
-
-               /* Register the PWM driver at "/dev/pwm" */
-               snprintf(devicename, 10, "/dev/pwm%d", ch);
-               ret = pwm_register(devicename, pwm);
-               if (ret < 0) {
-                       adbg("pwm_register failed: %d\n", ret);
-                       return;
-               }
-       }
-
-       return;
-}
-
-/**
- *
- * @brief    pwm driver register with channel and device name
- * @param    unsigned int channel : pwm channel
- * @param    char* devicename     : the buffer of device name
- * @return    == 0: register ok
- *            <  0: register fail
- * @note     note here
- */
-int s5j_board_pwm_setup(int32_t channel, char *devicename)
-{
-       struct pwm_lowerhalf_s *pwm;
-       int ret;
-
-       lldbg("s5j_board_pwm_setup\n");
-
-       /* Call s5j_pwminitialize() to get an instance of the PWM interface */
-       pwm = s5j_pwminitialize(channel);
-       if (!pwm) {
-               dbg("Failed to get the S5J PWM lower half\n");
-               return -ENODEV;
-       }
-
-       /* Register the PWM driver at "/dev/pwm0" */
-       ret = pwm_register(devicename, pwm);
-       if (ret < 0) {
-               adbg("pwm_register failed: %d\n", ret);
-               return ret;
-       }
-
-       return OK;
-}
index 7fd3226..61f63ee 100644 (file)
  * POSSIBILITY OF SUCH DAMAGE.
  *
  */
-
 /****************************************************************************
  * Included Files
  ****************************************************************************/
 
-#ifndef __ARCH_ARM_SRC_S5J_S5J_PWM_H
-#define __ARCH_ARM_SRC_S5J_S5J_PWM_H
+#ifndef        __S5J_PWM_H_
+#define        __S5J_PWM_H_
 
-#define __SYSCALL_USER_DEF        (0x10000000)
+/****************************************************************************
+ * Pre-proessor Definitions
+ ****************************************************************************/
+#define __SYSCALL_USER_DEF                     (0x10000000)
 
 /* Start user definition ioctl request for timer */
-#define __TIMER_USER_DEF          (0x10000000)
+#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_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
+
+#define TIME_NS     1
+#define TIME_MS     0
 
-#define PWM_START_ENABLE_TOUT     (__TIMER_USER_DEF + 0x10)
-#define PWM_START_ENABLE_ONETIME  (__TIMER_USER_DEF + 0x11)
+#define TIMER_SRC_PCLK  0
+#define TIMER_SRC_SCLK  1
 
-#define PWM_PCLK                  (26000000)
+#define MAX_NO_PWM      4
+#define TOTAL_NUMBER_OF_TIMER      8
+#define TOTAL_NUMBER_OF_PWMOUT      6
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* 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 */
+       cycle_t 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);
+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
index f64ae6c..999a24c 100644 (file)
@@ -13,6 +13,14 @@ config SIDK_S5JT200_TLC59116
                SIDK S5JT200 evaluation board has TLC59116 IC attached to
                its I2C bus. It can generate PWM signals to control RGB LEDs.
 
+config SIDK_S5JT200_PWM_CHNUM
+       int "Number of PWM channel"
+       default 6
+       depends on S5J_PWM
+       ---help---
+               Sets the number of pwm channel exposed on SIDK S5JT200
+               evaluation board
+
 config SIDK_S5JT200_FLASH_CAPACITY
        int "Size of external flash memory (in bytes)"
        default 8388608
index 43dc74a..fad0baa 100644 (file)
@@ -61,6 +61,8 @@ ifeq ($(CONFIG_SIDK_S5JT200_TLC59116),y)
 CSRCS += s5jt200_tlc59116.c
 endif
 
+CSRCS += s5jt200_pwm.c
+
 ifeq ($(CONFIG_ARCH_BUTTONS),y)
 CSRCS += s5jt200_buttons.c
 endif
index f412c96..3c4a6e6 100644 (file)
@@ -205,6 +205,10 @@ void board_initialize(void)
        slsi_driver_initialize();
 #endif
 
+#ifdef CONFIG_S5J_PWM
+       board_pwm_setup();
+#endif
+
        s5j_gpioinitialize();
 
 #ifdef CONFIG_SIDK_S5JT200_TLC59116
diff --git a/os/arch/arm/src/sidk_s5jt200/src/s5jt200_pwm.c b/os/arch/arm/src/sidk_s5jt200/src/s5jt200_pwm.c
new file mode 100644 (file)
index 0000000..5048df0
--- /dev/null
@@ -0,0 +1,99 @@
+/****************************************************************************
+ *
+ * Copyright 2016 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/sidk_s5jt200/src/s5jt200_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.
+ *
+ * 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.
+ *
+ */
+/****************************************************************************
+ * 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 <debug.h>
+#include <tinyara/pwm.h>
+
+#include "chip.h"
+#include "s5j_pwm.h"
+
+int board_pwm_setup(void)
+{
+#ifdef CONFIG_S5J_PWM
+       struct pwm_lowerhalf_s *pwm;
+       char path[10];
+       int ret;
+       int i;
+       for (i = 0; i < CONFIG_SIDK_S5JT200_PWM_CHNUM; i++) {
+               pwm = s5j_pwminitialize(i);
+               if (!pwm) {
+                       lldbg("Failed to get the S5J PWM lower half\n");
+                       return -ENODEV;
+               }
+
+               /* Register the PWM driver at "/dev/pwmx" */
+               snprintf(path, sizeof(path), "/dev/pwm%d", i);
+               ret = pwm_register(path, pwm);
+               if (ret < 0) {
+                       lldbg("pwm_register failed: %d\n", ret);
+                       return ret;
+               }
+       }
+#endif
+
+       return OK;
+}
index d6ec3c7..a39ce00 100644 (file)
@@ -81,7 +81,6 @@
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
-extern void pwmdrv_register(void);
 extern void s5j_i2c_register(int bus);
 
 char *s5j_get_binary_version(uint32_t baddr)
@@ -290,10 +289,6 @@ int board_app_initialize(void)
        s5j_i2c_register(1);
 #endif
 
-#ifdef CONFIG_S5J_PWM
-       pwmdrv_register();
-#endif
-
 #if defined(CONFIG_RTC) && defined(CONFIG_RTC_DRIVER) && defined(CONFIG_S5J_RTC)
        up_rtc_getdatetime(&tp);
        lldbg("RTC getdatetime %d/%d/%d/%d/%d/%d\n",