
resend again, I receive Message undeliverable
On 07/14/2012 12:11 AM, Zhong Hongbo wrote:
From: Zhong Hongbo bocui107@gmail.com
Signed-off-by: Zhong Hongbo bocui107@gmail.com
Change for V2:
- Change the type of the return value from unsinged int to unsinged long for s3c64xx_get_base_nand function.
arch/arm/cpu/arm1176/s3c64xx/Makefile | 1 + arch/arm/cpu/arm1176/s3c64xx/pwm.c | 189 +++++++++++++++++++++++++++ arch/arm/include/asm/arch-s3c64xx/pwm.h | 70 ++++++++++ arch/arm/include/asm/arch-s3c64xx/s3c6400.h | 56 ++------- arch/arm/include/asm/arch-s3c64xx/s3c64x0.h | 59 --------- include/configs/smdk6400.h | 3 + 6 files changed, 272 insertions(+), 106 deletions(-) create mode 100644 arch/arm/cpu/arm1176/s3c64xx/pwm.c create mode 100644 arch/arm/include/asm/arch-s3c64xx/pwm.h delete mode 100644 arch/arm/include/asm/arch-s3c64xx/s3c64x0.h
diff --git a/arch/arm/cpu/arm1176/s3c64xx/Makefile b/arch/arm/cpu/arm1176/s3c64xx/Makefile index 0785b19..966663f 100644 --- a/arch/arm/cpu/arm1176/s3c64xx/Makefile +++ b/arch/arm/cpu/arm1176/s3c64xx/Makefile @@ -32,6 +32,7 @@ SOBJS = reset.o
COBJS-$(CONFIG_S3C6400) += cpu_init.o speed.o COBJS-y += timer.o +COBJS-$(CONFIG_PWM) += pwm.o
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
diff --git a/arch/arm/cpu/arm1176/s3c64xx/pwm.c b/arch/arm/cpu/arm1176/s3c64xx/pwm.c new file mode 100644 index 0000000..d1d70ff --- /dev/null +++ b/arch/arm/cpu/arm1176/s3c64xx/pwm.c @@ -0,0 +1,189 @@ +/*
- Copyright (C) 2012
- Zhong Hongbo bocui107@gmail.com
- based on arch/arm/cpu/armv7/s5p-common/sromc.c
- See file CREDITS for list of people who contributed to this
- project.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307 USA
- */
+#include <common.h> +#include <errno.h> +#include <pwm.h> +#include <asm/io.h> +#include <asm/arch/s3c6400.h> +#include <asm/arch/pwm.h>
+int pwm_enable(int pwm_id) +{
- const struct s3c_timer *pwm =
(struct s3c_timer *)s3c64xx_get_base_timer();
- unsigned long tcon;
- tcon = readl(&pwm->tcon);
- tcon |= TCON_START(pwm_id);
- writel(tcon, &pwm->tcon);
- return 0;
+}
+void pwm_disable(int pwm_id) +{
- const struct s3c_timer *pwm =
(struct s3c_timer *)s3c64xx_get_base_timer();
- unsigned long tcon;
- tcon = readl(&pwm->tcon);
- tcon &= ~TCON_START(pwm_id);
- writel(tcon, &pwm->tcon);
+}
+static unsigned long pwm_calc_tin(int pwm_id, unsigned long freq) +{
- unsigned long tin_parent_rate;
- unsigned int div;
- tin_parent_rate = get_PCLK();
- for (div = 2; div <= 16; div *= 2) {
if ((tin_parent_rate / (div << 16)) < freq)
return tin_parent_rate / div;
- }
- return tin_parent_rate / 16;
+}
+#define NS_IN_HZ (1000000000UL)
+int pwm_config(int pwm_id, int duty_ns, int period_ns) +{
- const struct s3c_timer *pwm =
(struct s3c_timer *)s3c64xx_get_base_timer();
- unsigned int offset;
- unsigned long tin_rate;
- unsigned long tin_ns;
- unsigned long period;
- unsigned long tcon;
- unsigned long tcnt;
- unsigned long tcmp;
- /*
* We currently avoid using 64bit arithmetic by using the
* fact that anything faster than 1GHz is easily representable
* by 32bits.
*/
- if (period_ns > NS_IN_HZ || duty_ns > NS_IN_HZ)
return -ERANGE;
- if (duty_ns > period_ns)
return -EINVAL;
- period = NS_IN_HZ / period_ns;
- /* Check to see if we are changing the clock rate of the PWM */
- tin_rate = pwm_calc_tin(pwm_id, period);
- tin_ns = NS_IN_HZ / tin_rate;
- tcnt = period_ns / tin_ns;
- /* Note, counters count down */
- tcmp = duty_ns / tin_ns;
- tcmp = tcnt - tcmp;
- /*
* the pwm hw only checks the compare register after a decrement,
* so the pin never toggles if tcmp = tcnt
*/
- if (tcmp == tcnt)
tcmp--;
- if (tcmp < 0)
tcmp = 0;
- /* Update the PWM register block. */
- offset = pwm_id * 3;
- if (pwm_id < 4) {
writel(tcnt, &pwm->tcntb0 + offset);
writel(tcmp, &pwm->tcmpb0 + offset);
- }
- tcon = readl(&pwm->tcon);
- tcon |= TCON_UPDATE(pwm_id);
- if (pwm_id < 4)
tcon |= TCON_AUTO_RELOAD(pwm_id);
- else
tcon |= TCON4_AUTO_RELOAD;
- writel(tcon, &pwm->tcon);
- tcon &= ~TCON_UPDATE(pwm_id);
- writel(tcon, &pwm->tcon);
- return 0;
+}
+int pwm_init(int pwm_id, int div, int invert) +{
- u32 val;
- const struct s3c_timer *pwm =
(struct s3c_timer *)s3c64xx_get_base_timer();
- unsigned long timer_rate_hz;
- unsigned int offset, prescaler;
- /*
* Timer Freq(HZ) =
* PWM_CLK / { (prescaler_value + 1) * (divider_value) }
*/
- val = readl(&pwm->tcfg0);
- if (pwm_id < 2) {
prescaler = PRESCALER_0;
val &= ~0xff;
val |= (prescaler & 0xff);
- } else {
prescaler = PRESCALER_1;
val &= ~(0xff << 8);
val |= (prescaler & 0xff) << 8;
- }
- writel(val, &pwm->tcfg0);
- val = readl(&pwm->tcfg1);
- val &= ~(0xf << MUX_DIV_SHIFT(pwm_id));
- val |= (div & 0xf) << MUX_DIV_SHIFT(pwm_id);
- writel(val, &pwm->tcfg1);
- timer_rate_hz = get_PCLK() / ((prescaler + 1) *
(div + 1));
- timer_rate_hz = timer_rate_hz / CONFIG_SYS_HZ;
- /* set count value */
- offset = pwm_id * 3;
- writel(timer_rate_hz, &pwm->tcntb0 + offset);
- val = readl(&pwm->tcon) & ~(0xf << TCON_OFFSET(pwm_id));
- if (invert && (pwm_id < 4))
val |= TCON_INVERTER(pwm_id);
- writel(val, &pwm->tcon);
- pwm_enable(pwm_id);
- return 0;
+} diff --git a/arch/arm/include/asm/arch-s3c64xx/pwm.h b/arch/arm/include/asm/arch-s3c64xx/pwm.h new file mode 100644 index 0000000..1e18f8c --- /dev/null +++ b/arch/arm/include/asm/arch-s3c64xx/pwm.h @@ -0,0 +1,70 @@ +/*
- Copyright (C) 2012
- Zhong Hongbo bocui107@gmail.com
- based on arch/arm/include/asm/arch-s5pc1xx/pwm.h
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307 USA
- */
+#ifndef __ASM_ARM_ARCH_PWM_H_ +#define __ASM_ARM_ARCH_PWM_H_
+#define PRESCALER_0 (8 - 1) /* prescaler of timer 0, 1 */ +#define PRESCALER_1 (16 - 1) /* prescaler of timer 2, 3, 4 */
+/* Divider MUX */ +#define MUX_DIV_1 0 /* 1/1 period */ +#define MUX_DIV_2 1 /* 1/2 period */ +#define MUX_DIV_4 2 /* 1/4 period */ +#define MUX_DIV_8 3 /* 1/8 period */ +#define MUX_DIV_16 4 /* 1/16 period */
+#define MUX_DIV_SHIFT(x) (x * 4)
+#define TCON_OFFSET(x) ((x + 1) * (!!x) << 2)
+#define TCON_START(x) (1 << TCON_OFFSET(x)) +#define TCON_UPDATE(x) (1 << (TCON_OFFSET(x) + 1)) +#define TCON_INVERTER(x) (1 << (TCON_OFFSET(x) + 2)) +#define TCON_AUTO_RELOAD(x) (1 << (TCON_OFFSET(x) + 3)) +#define TCON4_AUTO_RELOAD (1 << 22)
+#define TCFG1_DMA(x) (x << 20)
+#ifndef __ASSEMBLY__ +struct s3c_timer {
- unsigned int tcfg0;
- unsigned int tcfg1;
- unsigned int tcon;
- unsigned int tcntb0;
- unsigned int tcmpb0;
- unsigned int tcnto0;
- unsigned int tcntb1;
- unsigned int tcmpb1;
- unsigned int tcnto1;
- unsigned int tcntb2;
- unsigned int res1;
- unsigned int tcnto2;
- unsigned int tcntb3;
- unsigned int res2;
- unsigned int tcnto3;
- unsigned int tcntb4;
- unsigned int tcnto4;
- unsigned int tint_cstat;
+}; +#endif +#endif diff --git a/arch/arm/include/asm/arch-s3c64xx/s3c6400.h b/arch/arm/include/asm/arch-s3c64xx/s3c6400.h index 77b9509..b884763 100644 --- a/arch/arm/include/asm/arch-s3c64xx/s3c6400.h +++ b/arch/arm/include/asm/arch-s3c64xx/s3c6400.h @@ -31,6 +31,10 @@ #ifndef __S3C6400_H__ #define __S3C6400_H__
+#if defined(CONFIG_SYNC_MODE) && defined(CONFIG_S3C6400) +#error CONFIG_SYNC_MODE unavailable on S3C6400, please, fix your configuration! +#endif
#define S3C64XX_UART_CHANNELS 3 #define S3C64XX_SPI_CHANNELS 2
@@ -587,51 +591,6 @@ */ #define ELFIN_TIMER_BASE 0x7F006000
-#define TCFG0_REG __REG(0x7F006000) -#define TCFG1_REG __REG(0x7F006004) -#define TCON_REG __REG(0x7F006008) -#define TCNTB0_REG __REG(0x7F00600c) -#define TCMPB0_REG __REG(0x7F006010) -#define TCNTO0_REG __REG(0x7F006014) -#define TCNTB1_REG __REG(0x7F006018) -#define TCMPB1_REG __REG(0x7F00601c) -#define TCNTO1_REG __REG(0x7F006020) -#define TCNTB2_REG __REG(0x7F006024) -#define TCMPB2_REG __REG(0x7F006028) -#define TCNTO2_REG __REG(0x7F00602c) -#define TCNTB3_REG __REG(0x7F006030) -#define TCMPB3_REG __REG(0x7F006034) -#define TCNTO3_REG __REG(0x7F006038) -#define TCNTB4_REG __REG(0x7F00603c) -#define TCNTO4_REG __REG(0x7F006040)
-/* Fields */ -#define fTCFG0_DZONE Fld(8, 16) /* the dead zone length (=timer 0) */ -#define fTCFG0_PRE1 Fld(8, 8) /* prescaler value for time 2,3,4 */ -#define fTCFG0_PRE0 Fld(8, 0) /* prescaler value for time 0,1 */ -#define fTCFG1_MUX4 Fld(4, 16) -/* bits */ -#define TCFG0_DZONE(x) FInsrt((x), fTCFG0_DZONE) -#define TCFG0_PRE1(x) FInsrt((x), fTCFG0_PRE1) -#define TCFG0_PRE0(x) FInsrt((x), fTCFG0_PRE0) -#define TCON_4_AUTO (1 << 22) /* auto reload on/off for Timer 4 */ -#define TCON_4_UPDATE (1 << 21) /* manual Update TCNTB4 */ -#define TCON_4_ONOFF (1 << 20) /* 0: Stop, 1: start Timer 4 */ -#define COUNT_4_ON (TCON_4_ONOFF * 1) -#define COUNT_4_OFF (TCON_4_ONOFF * 0) -#define TCON_3_AUTO (1 << 19) /* auto reload on/off for Timer 3 */ -#define TIMER3_ATLOAD_ON (TCON_3_AUTO * 1) -#define TIMER3_ATLAOD_OFF FClrBit(TCON, TCON_3_AUTO) -#define TCON_3_INVERT (1 << 18) /* 1: Inverter on for TOUT3 */ -#define TIMER3_IVT_ON (TCON_3_INVERT * 1) -#define TIMER3_IVT_OFF (FClrBit(TCON, TCON_3_INVERT)) -#define TCON_3_MAN (1 << 17) /* manual Update TCNTB3,TCMPB3 */ -#define TIMER3_MANUP (TCON_3_MAN*1) -#define TIMER3_NOP (FClrBit(TCON, TCON_3_MAN)) -#define TCON_3_ONOFF (1 << 16) /* 0: Stop, 1: start Timer 3 */ -#define TIMER3_ON (TCON_3_ONOFF * 1) -#define TIMER3_OFF (FClrBit(TCON, TCON_3_ONOFF))
#if defined(CONFIG_CLK_400_100_50) #define STARTUP_AMDIV 400 #define STARTUP_MDIV 400 @@ -749,8 +708,6 @@
#ifndef __ASSEMBLY__
-#include "s3c64x0.h"
static inline unsigned long s3c64xx_get_base_uart(void) { return ELFIN_UART_BASE; @@ -760,6 +717,11 @@ static inline unsigned long s3c64xx_get_base_nand(void) { return ELFIN_NAND_BASE; }
+static inline unsigned long s3c64xx_get_base_timer(void) +{
- return ELFIN_TIMER_BASE;
+} #endif
#endif /*__S3C6400_H__*/ diff --git a/arch/arm/include/asm/arch-s3c64xx/s3c64x0.h b/arch/arm/include/asm/arch-s3c64xx/s3c64x0.h deleted file mode 100644 index 7add68c..0000000 --- a/arch/arm/include/asm/arch-s3c64xx/s3c64x0.h +++ /dev/null @@ -1,59 +0,0 @@ -/*
- (C) Copyright 2003
- David MÃŒller ELSOFT AG Switzerland. d.mueller@elsoft.ch
- (C) Copyright 2008
- Guennadi Liakhovetki, DENX Software Engineering, lg@denx.de
- See file CREDITS for list of people who contributed to this
- project.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307 USA
- */
-/************************************************
- NAME : S3C64XX.h
- Version : 31.3.2003
- common stuff for SAMSUNG S3C64XX SoC
- ************************************************/
-#ifndef __S3C64XX_H__ -#define __S3C64XX_H__
-#if defined(CONFIG_SYNC_MODE) && defined(CONFIG_S3C6400) -#error CONFIG_SYNC_MODE unavailable on S3C6400, please, fix your configuration! -#endif
-#include <asm/types.h>
-/* PWM TIMER (see manual chapter 10) */ -typedef struct {
- volatile u32 TCNTB;
- volatile u32 TCMPB;
- volatile u32 TCNTO;
-} s3c64xx_timer;
-typedef struct {
- volatile u32 TCFG0;
- volatile u32 TCFG1;
- volatile u32 TCON;
- s3c64xx_timer ch[4];
- volatile u32 TCNTB4;
- volatile u32 TCNTO4;
-} s3c64xx_timers;
-#endif /*__S3C64XX_H__*/ diff --git a/include/configs/smdk6400.h b/include/configs/smdk6400.h index 47326d6..3642a5c 100644 --- a/include/configs/smdk6400.h +++ b/include/configs/smdk6400.h @@ -141,6 +141,9 @@
#define CONFIG_SYS_HZ 1000
+/* PWM */ +#define CONFIG_PWM 1
/*-----------------------------------------------------------------------
- Stack sizes