aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /arch/blackfin
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'arch/blackfin')
-rw-r--r--arch/blackfin/ADI_BSD.txt41
-rw-r--r--arch/blackfin/include/asm/byteorder.h1
-rw-r--r--arch/blackfin/include/asm/cachectl.h20
-rw-r--r--arch/blackfin/include/asm/fcntl.h17
-rw-r--r--arch/blackfin/include/asm/ioctls.h7
-rw-r--r--arch/blackfin/include/asm/mutex.h1
-rw-r--r--arch/blackfin/include/asm/poll.h16
-rw-r--r--arch/blackfin/include/asm/posix_types.h33
-rw-r--r--arch/blackfin/include/asm/sigcontext.h61
-rw-r--r--arch/blackfin/include/asm/siginfo.h41
-rw-r--r--arch/blackfin/include/asm/signal.h7
-rw-r--r--arch/blackfin/include/asm/stat.h69
-rw-r--r--arch/blackfin/include/asm/swab.h50
-rw-r--r--arch/blackfin/include/asm/system.h192
-rw-r--r--arch/blackfin/kernel/bfin_dma_5xx.c536
-rw-r--r--arch/blackfin/kernel/init_task.c32
-rw-r--r--arch/blackfin/kernel/pwm.c100
17 files changed, 1224 insertions, 0 deletions
diff --git a/arch/blackfin/ADI_BSD.txt b/arch/blackfin/ADI_BSD.txt
new file mode 100644
index 00000000000..501d0b64594
--- /dev/null
+++ b/arch/blackfin/ADI_BSD.txt
@@ -0,0 +1,41 @@
1This BSD-Style License applies to a few files in ./arch/blackfin directory,
2and is included here, so people understand which code they can use outside
3the Linux kernel, in non-GPL based projects.
4
5Using the files released under the "ADI BSD" license, must comply with
6these license terms.
7
8--------------------------------------------------------------------------
9
10Copyright Analog Devices, Inc.
11
12All rights reserved.
13
14Redistribution and use in source and binary forms, with or without
15modification, are permitted provided that the following conditions
16are met:
17 - Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
19 - Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in
21 the documentation and/or other materials provided with the
22 distribution.
23 - Neither the name of Analog Devices, Inc. nor the names of its
24 contributors may be used to endorse or promote products derived
25 from this software without specific prior written permission.
26 - The use of this software may or may not infringe the patent rights
27 of one or more patent holders. This license does not release you
28 from the requirement that you obtain separate licenses from these
29 patent holders to use this software.
30
31THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
32IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
33MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
35INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
36BUT NOT LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF
37SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
38BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
39WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
40OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
diff --git a/arch/blackfin/include/asm/byteorder.h b/arch/blackfin/include/asm/byteorder.h
new file mode 100644
index 00000000000..9558416d578
--- /dev/null
+++ b/arch/blackfin/include/asm/byteorder.h
@@ -0,0 +1 @@
#include <linux/byteorder/little_endian.h>
diff --git a/arch/blackfin/include/asm/cachectl.h b/arch/blackfin/include/asm/cachectl.h
new file mode 100644
index 00000000000..03255df6c1e
--- /dev/null
+++ b/arch/blackfin/include/asm/cachectl.h
@@ -0,0 +1,20 @@
1/*
2 * based on the mips/cachectl.h
3 *
4 * Copyright 2010 Analog Devices Inc.
5 * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
6 *
7 * Licensed under the GPL-2 or later.
8 */
9
10#ifndef _ASM_CACHECTL
11#define _ASM_CACHECTL
12
13/*
14 * Options for cacheflush system call
15 */
16#define ICACHE (1<<0) /* flush instruction cache */
17#define DCACHE (1<<1) /* writeback and flush data cache */
18#define BCACHE (ICACHE|DCACHE) /* flush both caches */
19
20#endif /* _ASM_CACHECTL */
diff --git a/arch/blackfin/include/asm/fcntl.h b/arch/blackfin/include/asm/fcntl.h
new file mode 100644
index 00000000000..251c911d59c
--- /dev/null
+++ b/arch/blackfin/include/asm/fcntl.h
@@ -0,0 +1,17 @@
1/*
2 * Copyright 2004-2008 Analog Devices Inc.
3 *
4 * Licensed under the GPL-2 or later.
5 */
6
7#ifndef _BFIN_FCNTL_H
8#define _BFIN_FCNTL_H
9
10#define O_DIRECTORY 040000 /* must be a directory */
11#define O_NOFOLLOW 0100000 /* don't follow links */
12#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
13#define O_LARGEFILE 0400000
14
15#include <asm-generic/fcntl.h>
16
17#endif
diff --git a/arch/blackfin/include/asm/ioctls.h b/arch/blackfin/include/asm/ioctls.h
new file mode 100644
index 00000000000..eca8d75b0a8
--- /dev/null
+++ b/arch/blackfin/include/asm/ioctls.h
@@ -0,0 +1,7 @@
1#ifndef __ARCH_BFIN_IOCTLS_H__
2#define __ARCH_BFIN_IOCTLS_H__
3
4#define FIOQSIZE 0x545E
5#include <asm-generic/ioctls.h>
6
7#endif
diff --git a/arch/blackfin/include/asm/mutex.h b/arch/blackfin/include/asm/mutex.h
new file mode 100644
index 00000000000..ff6101aa2c7
--- /dev/null
+++ b/arch/blackfin/include/asm/mutex.h
@@ -0,0 +1 @@
#include <asm-generic/mutex-dec.h>
diff --git a/arch/blackfin/include/asm/poll.h b/arch/blackfin/include/asm/poll.h
new file mode 100644
index 00000000000..072d8966c5c
--- /dev/null
+++ b/arch/blackfin/include/asm/poll.h
@@ -0,0 +1,16 @@
1/*
2 * Copyright 2004-2009 Analog Devices Inc.
3 *
4 * Licensed under the GPL-2 or later.
5 *
6 */
7
8#ifndef __BFIN_POLL_H
9#define __BFIN_POLL_H
10
11#define POLLWRNORM 4 /* POLLOUT */
12#define POLLWRBAND 256
13
14#include <asm-generic/poll.h>
15
16#endif
diff --git a/arch/blackfin/include/asm/posix_types.h b/arch/blackfin/include/asm/posix_types.h
new file mode 100644
index 00000000000..41bc1875c4d
--- /dev/null
+++ b/arch/blackfin/include/asm/posix_types.h
@@ -0,0 +1,33 @@
1/*
2 * Copyright 2004-2009 Analog Devices Inc.
3 *
4 * Licensed under the GPL-2 or later.
5 */
6
7#ifndef __ARCH_BFIN_POSIX_TYPES_H
8#define __ARCH_BFIN_POSIX_TYPES_H
9
10typedef unsigned short __kernel_mode_t;
11#define __kernel_mode_t __kernel_mode_t
12
13typedef unsigned short __kernel_nlink_t;
14#define __kernel_nlink_t __kernel_nlink_t
15
16typedef unsigned int __kernel_ipc_pid_t;
17#define __kernel_ipc_pid_t __kernel_ipc_pid_t
18
19typedef unsigned long __kernel_size_t;
20typedef long __kernel_ssize_t;
21typedef int __kernel_ptrdiff_t;
22#define __kernel_size_t __kernel_size_t
23
24typedef unsigned short __kernel_old_uid_t;
25typedef unsigned short __kernel_old_gid_t;
26#define __kernel_old_uid_t __kernel_old_uid_t
27
28typedef unsigned short __kernel_old_dev_t;
29#define __kernel_old_dev_t __kernel_old_dev_t
30
31#include <asm-generic/posix_types.h>
32
33#endif
diff --git a/arch/blackfin/include/asm/sigcontext.h b/arch/blackfin/include/asm/sigcontext.h
new file mode 100644
index 00000000000..906bdc1f5fd
--- /dev/null
+++ b/arch/blackfin/include/asm/sigcontext.h
@@ -0,0 +1,61 @@
1/*
2 * Copyright 2004-2008 Analog Devices Inc.
3 *
4 * Licensed under the GPL-2 or later.
5 */
6
7#ifndef _ASM_BLACKFIN_SIGCONTEXT_H
8#define _ASM_BLACKFIN_SIGCONTEXT_H
9
10/* Add new entries at the end of the structure only. */
11struct sigcontext {
12 unsigned long sc_r0;
13 unsigned long sc_r1;
14 unsigned long sc_r2;
15 unsigned long sc_r3;
16 unsigned long sc_r4;
17 unsigned long sc_r5;
18 unsigned long sc_r6;
19 unsigned long sc_r7;
20 unsigned long sc_p0;
21 unsigned long sc_p1;
22 unsigned long sc_p2;
23 unsigned long sc_p3;
24 unsigned long sc_p4;
25 unsigned long sc_p5;
26 unsigned long sc_usp;
27 unsigned long sc_a0w;
28 unsigned long sc_a1w;
29 unsigned long sc_a0x;
30 unsigned long sc_a1x;
31 unsigned long sc_astat;
32 unsigned long sc_rets;
33 unsigned long sc_pc;
34 unsigned long sc_retx;
35 unsigned long sc_fp;
36 unsigned long sc_i0;
37 unsigned long sc_i1;
38 unsigned long sc_i2;
39 unsigned long sc_i3;
40 unsigned long sc_m0;
41 unsigned long sc_m1;
42 unsigned long sc_m2;
43 unsigned long sc_m3;
44 unsigned long sc_l0;
45 unsigned long sc_l1;
46 unsigned long sc_l2;
47 unsigned long sc_l3;
48 unsigned long sc_b0;
49 unsigned long sc_b1;
50 unsigned long sc_b2;
51 unsigned long sc_b3;
52 unsigned long sc_lc0;
53 unsigned long sc_lc1;
54 unsigned long sc_lt0;
55 unsigned long sc_lt1;
56 unsigned long sc_lb0;
57 unsigned long sc_lb1;
58 unsigned long sc_seqstat;
59};
60
61#endif
diff --git a/arch/blackfin/include/asm/siginfo.h b/arch/blackfin/include/asm/siginfo.h
new file mode 100644
index 00000000000..3e81306394e
--- /dev/null
+++ b/arch/blackfin/include/asm/siginfo.h
@@ -0,0 +1,41 @@
1/*
2 * Copyright 2004-2008 Analog Devices Inc.
3 *
4 * Licensed under the GPL-2 or later.
5 */
6
7#ifndef _BFIN_SIGINFO_H
8#define _BFIN_SIGINFO_H
9
10#include <linux/types.h>
11#include <asm-generic/siginfo.h>
12
13#define UID16_SIGINFO_COMPAT_NEEDED
14
15#define si_uid16 _sifields._kill._uid
16
17#define ILL_ILLPARAOP (__SI_FAULT|2) /* illegal opcode combine ********** */
18#define ILL_ILLEXCPT (__SI_FAULT|4) /* unrecoverable exception ********** */
19#define ILL_CPLB_VI (__SI_FAULT|9) /* D/I CPLB protect violation ******** */
20#define ILL_CPLB_MISS (__SI_FAULT|10) /* D/I CPLB miss ******** */
21#define ILL_CPLB_MULHIT (__SI_FAULT|11) /* D/I CPLB multiple hit ******** */
22
23/*
24 * SIGBUS si_codes
25 */
26#define BUS_OPFETCH (__SI_FAULT|4) /* error from instruction fetch ******** */
27
28/*
29 * SIGTRAP si_codes
30 */
31#define TRAP_STEP (__SI_FAULT|1) /* single-step breakpoint************* */
32#define TRAP_TRACEFLOW (__SI_FAULT|2) /* trace buffer overflow ************* */
33#define TRAP_WATCHPT (__SI_FAULT|3) /* watchpoint match ************* */
34#define TRAP_ILLTRAP (__SI_FAULT|4) /* illegal trap ************* */
35
36/*
37 * SIGSEGV si_codes
38 */
39#define SEGV_STACKFLOW (__SI_FAULT|3) /* stack overflow */
40
41#endif
diff --git a/arch/blackfin/include/asm/signal.h b/arch/blackfin/include/asm/signal.h
new file mode 100644
index 00000000000..77a3bf37b69
--- /dev/null
+++ b/arch/blackfin/include/asm/signal.h
@@ -0,0 +1,7 @@
1#ifndef _BLACKFIN_SIGNAL_H
2#define _BLACKFIN_SIGNAL_H
3
4#define SA_RESTORER 0x04000000
5#include <asm-generic/signal.h>
6
7#endif
diff --git a/arch/blackfin/include/asm/stat.h b/arch/blackfin/include/asm/stat.h
new file mode 100644
index 00000000000..2e27665c4e9
--- /dev/null
+++ b/arch/blackfin/include/asm/stat.h
@@ -0,0 +1,69 @@
1/*
2 * Copyright 2004-2006 Analog Devices Inc.
3 *
4 * Licensed under the GPL-2.
5 */
6
7#ifndef _BFIN_STAT_H
8#define _BFIN_STAT_H
9
10struct stat {
11 unsigned short st_dev;
12 unsigned short __pad1;
13 unsigned long st_ino;
14 unsigned short st_mode;
15 unsigned short st_nlink;
16 unsigned short st_uid;
17 unsigned short st_gid;
18 unsigned short st_rdev;
19 unsigned short __pad2;
20 unsigned long st_size;
21 unsigned long st_blksize;
22 unsigned long st_blocks;
23 unsigned long st_atime;
24 unsigned long __unused1;
25 unsigned long st_mtime;
26 unsigned long __unused2;
27 unsigned long st_ctime;
28 unsigned long __unused3;
29 unsigned long __unused4;
30 unsigned long __unused5;
31};
32
33/* This matches struct stat64 in glibc2.1, hence the absolutely
34 * insane amounts of padding around dev_t's.
35 */
36struct stat64 {
37 unsigned long long st_dev;
38 unsigned char __pad1[4];
39
40#define STAT64_HAS_BROKEN_ST_INO 1
41 unsigned long __st_ino;
42
43 unsigned int st_mode;
44 unsigned int st_nlink;
45
46 unsigned long st_uid;
47 unsigned long st_gid;
48
49 unsigned long long st_rdev;
50 unsigned char __pad2[4];
51
52 long long st_size;
53 unsigned long st_blksize;
54
55 long long st_blocks; /* Number 512-byte blocks allocated. */
56
57 unsigned long st_atime;
58 unsigned long st_atime_nsec;
59
60 unsigned long st_mtime;
61 unsigned long st_mtime_nsec;
62
63 unsigned long st_ctime;
64 unsigned long st_ctime_nsec;
65
66 unsigned long long st_ino;
67};
68
69#endif /* _BFIN_STAT_H */
diff --git a/arch/blackfin/include/asm/swab.h b/arch/blackfin/include/asm/swab.h
new file mode 100644
index 00000000000..89de6507ca2
--- /dev/null
+++ b/arch/blackfin/include/asm/swab.h
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2009 Analog Devices Inc.
3 *
4 * Licensed under the GPL-2 or later.
5 */
6
7#ifndef _BLACKFIN_SWAB_H
8#define _BLACKFIN_SWAB_H
9
10#include <linux/types.h>
11#include <asm-generic/swab.h>
12
13#ifdef __GNUC__
14
15static __inline__ __attribute_const__ __u32 __arch_swahb32(__u32 xx)
16{
17 __u32 tmp;
18 __asm__("%1 = %0 >> 8 (V);\n\t"
19 "%0 = %0 << 8 (V);\n\t"
20 "%0 = %0 | %1;\n\t"
21 : "+d"(xx), "=&d"(tmp));
22 return xx;
23}
24#define __arch_swahb32 __arch_swahb32
25
26static __inline__ __attribute_const__ __u32 __arch_swahw32(__u32 xx)
27{
28 __u32 rv;
29 __asm__("%0 = PACK(%1.L, %1.H);\n\t": "=d"(rv): "d"(xx));
30 return rv;
31}
32#define __arch_swahw32 __arch_swahw32
33
34static __inline__ __attribute_const__ __u32 __arch_swab32(__u32 xx)
35{
36 return __arch_swahb32(__arch_swahw32(xx));
37}
38#define __arch_swab32 __arch_swab32
39
40static __inline__ __attribute_const__ __u16 __arch_swab16(__u16 xx)
41{
42 __u32 xw = xx;
43 __asm__("%0 <<= 8;\n %0.L = %0.L + %0.H (NS);\n": "+d"(xw));
44 return (__u16)xw;
45}
46#define __arch_swab16 __arch_swab16
47
48#endif /* __GNUC__ */
49
50#endif /* _BLACKFIN_SWAB_H */
diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h
new file mode 100644
index 00000000000..44bd0cced72
--- /dev/null
+++ b/arch/blackfin/include/asm/system.h
@@ -0,0 +1,192 @@
1/*
2 * Copyright 2004-2009 Analog Devices Inc.
3 * Tony Kou (tonyko@lineo.ca)
4 *
5 * Licensed under the GPL-2 or later
6 */
7
8#ifndef _BLACKFIN_SYSTEM_H
9#define _BLACKFIN_SYSTEM_H
10
11#include <linux/linkage.h>
12#include <linux/irqflags.h>
13#include <mach/anomaly.h>
14#include <asm/cache.h>
15#include <asm/pda.h>
16#include <asm/irq.h>
17
18/*
19 * Force strict CPU ordering.
20 */
21#define nop() __asm__ __volatile__ ("nop;\n\t" : : )
22#define smp_mb() mb()
23#define smp_rmb() rmb()
24#define smp_wmb() wmb()
25#define set_mb(var, value) do { var = value; mb(); } while (0)
26#define smp_read_barrier_depends() read_barrier_depends()
27
28#ifdef CONFIG_SMP
29asmlinkage unsigned long __raw_xchg_1_asm(volatile void *ptr, unsigned long value);
30asmlinkage unsigned long __raw_xchg_2_asm(volatile void *ptr, unsigned long value);
31asmlinkage unsigned long __raw_xchg_4_asm(volatile void *ptr, unsigned long value);
32asmlinkage unsigned long __raw_cmpxchg_1_asm(volatile void *ptr,
33 unsigned long new, unsigned long old);
34asmlinkage unsigned long __raw_cmpxchg_2_asm(volatile void *ptr,
35 unsigned long new, unsigned long old);
36asmlinkage unsigned long __raw_cmpxchg_4_asm(volatile void *ptr,
37 unsigned long new, unsigned long old);
38
39#ifdef __ARCH_SYNC_CORE_DCACHE
40/* Force Core data cache coherence */
41# define mb() do { barrier(); smp_check_barrier(); smp_mark_barrier(); } while (0)
42# define rmb() do { barrier(); smp_check_barrier(); } while (0)
43# define wmb() do { barrier(); smp_mark_barrier(); } while (0)
44# define read_barrier_depends() do { barrier(); smp_check_barrier(); } while (0)
45#else
46# define mb() barrier()
47# define rmb() barrier()
48# define wmb() barrier()
49# define read_barrier_depends() do { } while (0)
50#endif
51
52static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
53 int size)
54{
55 unsigned long tmp;
56
57 switch (size) {
58 case 1:
59 tmp = __raw_xchg_1_asm(ptr, x);
60 break;
61 case 2:
62 tmp = __raw_xchg_2_asm(ptr, x);
63 break;
64 case 4:
65 tmp = __raw_xchg_4_asm(ptr, x);
66 break;
67 }
68
69 return tmp;
70}
71
72/*
73 * Atomic compare and exchange. Compare OLD with MEM, if identical,
74 * store NEW in MEM. Return the initial value in MEM. Success is
75 * indicated by comparing RETURN with OLD.
76 */
77static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
78 unsigned long new, int size)
79{
80 unsigned long tmp;
81
82 switch (size) {
83 case 1:
84 tmp = __raw_cmpxchg_1_asm(ptr, new, old);
85 break;
86 case 2:
87 tmp = __raw_cmpxchg_2_asm(ptr, new, old);
88 break;
89 case 4:
90 tmp = __raw_cmpxchg_4_asm(ptr, new, old);
91 break;
92 }
93
94 return tmp;
95}
96#define cmpxchg(ptr, o, n) \
97 ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
98 (unsigned long)(n), sizeof(*(ptr))))
99
100#else /* !CONFIG_SMP */
101
102#define mb() barrier()
103#define rmb() barrier()
104#define wmb() barrier()
105#define read_barrier_depends() do { } while (0)
106
107struct __xchg_dummy {
108 unsigned long a[100];
109};
110#define __xg(x) ((volatile struct __xchg_dummy *)(x))
111
112#include <mach/blackfin.h>
113
114static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
115 int size)
116{
117 unsigned long tmp = 0;
118 unsigned long flags;
119
120 flags = hard_local_irq_save();
121
122 switch (size) {
123 case 1:
124 __asm__ __volatile__
125 ("%0 = b%2 (z);\n\t"
126 "b%2 = %1;\n\t"
127 : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
128 break;
129 case 2:
130 __asm__ __volatile__
131 ("%0 = w%2 (z);\n\t"
132 "w%2 = %1;\n\t"
133 : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
134 break;
135 case 4:
136 __asm__ __volatile__
137 ("%0 = %2;\n\t"
138 "%2 = %1;\n\t"
139 : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
140 break;
141 }
142 hard_local_irq_restore(flags);
143 return tmp;
144}
145
146#include <asm-generic/cmpxchg-local.h>
147
148/*
149 * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
150 * them available.
151 */
152#define cmpxchg_local(ptr, o, n) \
153 ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
154 (unsigned long)(n), sizeof(*(ptr))))
155#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
156
157#include <asm-generic/cmpxchg.h>
158
159#endif /* !CONFIG_SMP */
160
161#define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
162#define tas(ptr) ((void)xchg((ptr), 1))
163
164#define prepare_to_switch() do { } while(0)
165
166/*
167 * switch_to(n) should switch tasks to task ptr, first checking that
168 * ptr isn't the current task, in which case it does nothing.
169 */
170
171#include <asm/l1layout.h>
172#include <asm/mem_map.h>
173
174asmlinkage struct task_struct *resume(struct task_struct *prev, struct task_struct *next);
175
176#ifndef CONFIG_SMP
177#define switch_to(prev,next,last) \
178do { \
179 memcpy (&task_thread_info(prev)->l1_task_info, L1_SCRATCH_TASK_INFO, \
180 sizeof *L1_SCRATCH_TASK_INFO); \
181 memcpy (L1_SCRATCH_TASK_INFO, &task_thread_info(next)->l1_task_info, \
182 sizeof *L1_SCRATCH_TASK_INFO); \
183 (last) = resume (prev, next); \
184} while (0)
185#else
186#define switch_to(prev, next, last) \
187do { \
188 (last) = resume(prev, next); \
189} while (0)
190#endif
191
192#endif /* _BLACKFIN_SYSTEM_H */
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
new file mode 100644
index 00000000000..71dbaa4a48a
--- /dev/null
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -0,0 +1,536 @@
1/*
2 * bfin_dma_5xx.c - Blackfin DMA implementation
3 *
4 * Copyright 2004-2008 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/errno.h>
10#include <linux/interrupt.h>
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/param.h>
14#include <linux/proc_fs.h>
15#include <linux/sched.h>
16#include <linux/seq_file.h>
17#include <linux/spinlock.h>
18
19#include <asm/blackfin.h>
20#include <asm/cacheflush.h>
21#include <asm/dma.h>
22#include <asm/uaccess.h>
23#include <asm/early_printk.h>
24
25/*
26 * To make sure we work around 05000119 - we always check DMA_DONE bit,
27 * never the DMA_RUN bit
28 */
29
30struct dma_channel dma_ch[MAX_DMA_CHANNELS];
31EXPORT_SYMBOL(dma_ch);
32
33static int __init blackfin_dma_init(void)
34{
35 int i;
36
37 printk(KERN_INFO "Blackfin DMA Controller\n");
38
39
40#if ANOMALY_05000480
41 bfin_write_DMAC_TC_PER(0x0111);
42#endif
43
44 for (i = 0; i < MAX_DMA_CHANNELS; i++) {
45 atomic_set(&dma_ch[i].chan_status, 0);
46 dma_ch[i].regs = dma_io_base_addr[i];
47 }
48 /* Mark MEMDMA Channel 0 as requested since we're using it internally */
49 request_dma(CH_MEM_STREAM0_DEST, "Blackfin dma_memcpy");
50 request_dma(CH_MEM_STREAM0_SRC, "Blackfin dma_memcpy");
51
52#if defined(CONFIG_DEB_DMA_URGENT)
53 bfin_write_EBIU_DDRQUE(bfin_read_EBIU_DDRQUE()
54 | DEB1_URGENT | DEB2_URGENT | DEB3_URGENT);
55#endif
56
57 return 0;
58}
59arch_initcall(blackfin_dma_init);
60
61#ifdef CONFIG_PROC_FS
62static int proc_dma_show(struct seq_file *m, void *v)
63{
64 int i;
65
66 for (i = 0; i < MAX_DMA_CHANNELS; ++i)
67 if (dma_channel_active(i))
68 seq_printf(m, "%2d: %s\n", i, dma_ch[i].device_id);
69
70 return 0;
71}
72
73static int proc_dma_open(struct inode *inode, struct file *file)
74{
75 return single_open(file, proc_dma_show, NULL);
76}
77
78static const struct file_operations proc_dma_operations = {
79 .open = proc_dma_open,
80 .read = seq_read,
81 .llseek = seq_lseek,
82 .release = single_release,
83};
84
85static int __init proc_dma_init(void)
86{
87 return proc_create("dma", 0, NULL, &proc_dma_operations) != NULL;
88}
89late_initcall(proc_dma_init);
90#endif
91
92static void set_dma_peripheral_map(unsigned int channel, const char *device_id)
93{
94#ifdef CONFIG_BF54x
95 unsigned int per_map;
96
97 switch (channel) {
98 case CH_UART2_RX: per_map = 0xC << 12; break;
99 case CH_UART2_TX: per_map = 0xD << 12; break;
100 case CH_UART3_RX: per_map = 0xE << 12; break;
101 case CH_UART3_TX: per_map = 0xF << 12; break;
102 default: return;
103 }
104
105 if (strncmp(device_id, "BFIN_UART", 9) == 0)
106 dma_ch[channel].regs->peripheral_map = per_map;
107#endif
108}
109
110/**
111 * request_dma - request a DMA channel
112 *
113 * Request the specific DMA channel from the system if it's available.
114 */
115int request_dma(unsigned int channel, const char *device_id)
116{
117 pr_debug("request_dma() : BEGIN\n");
118
119 if (device_id == NULL)
120 printk(KERN_WARNING "request_dma(%u): no device_id given\n", channel);
121
122#if defined(CONFIG_BF561) && ANOMALY_05000182
123 if (channel >= CH_IMEM_STREAM0_DEST && channel <= CH_IMEM_STREAM1_DEST) {
124 if (get_cclk() > 500000000) {
125 printk(KERN_WARNING
126 "Request IMDMA failed due to ANOMALY 05000182\n");
127 return -EFAULT;
128 }
129 }
130#endif
131
132 if (atomic_cmpxchg(&dma_ch[channel].chan_status, 0, 1)) {
133 pr_debug("DMA CHANNEL IN USE\n");
134 return -EBUSY;
135 }
136
137 set_dma_peripheral_map(channel, device_id);
138 dma_ch[channel].device_id = device_id;
139 dma_ch[channel].irq = 0;
140
141 /* This is to be enabled by putting a restriction -
142 * you have to request DMA, before doing any operations on
143 * descriptor/channel
144 */
145 pr_debug("request_dma() : END\n");
146 return 0;
147}
148EXPORT_SYMBOL(request_dma);
149
150int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data)
151{
152 int ret;
153 unsigned int irq;
154
155 BUG_ON(channel >= MAX_DMA_CHANNELS || !callback ||
156 !atomic_read(&dma_ch[channel].chan_status));
157
158 irq = channel2irq(channel);
159 ret = request_irq(irq, callback, 0, dma_ch[channel].device_id, data);
160 if (ret)
161 return ret;
162
163 dma_ch[channel].irq = irq;
164 dma_ch[channel].data = data;
165
166 return 0;
167}
168EXPORT_SYMBOL(set_dma_callback);
169
170/**
171 * clear_dma_buffer - clear DMA fifos for specified channel
172 *
173 * Set the Buffer Clear bit in the Configuration register of specific DMA
174 * channel. This will stop the descriptor based DMA operation.
175 */
176static void clear_dma_buffer(unsigned int channel)
177{
178 dma_ch[channel].regs->cfg |= RESTART;
179 SSYNC();
180 dma_ch[channel].regs->cfg &= ~RESTART;
181}
182
183void free_dma(unsigned int channel)
184{
185 pr_debug("freedma() : BEGIN\n");
186 BUG_ON(channel >= MAX_DMA_CHANNELS ||
187 !atomic_read(&dma_ch[channel].chan_status));
188
189 /* Halt the DMA */
190 disable_dma(channel);
191 clear_dma_buffer(channel);
192
193 if (dma_ch[channel].irq)
194 free_irq(dma_ch[channel].irq, dma_ch[channel].data);
195
196 /* Clear the DMA Variable in the Channel */
197 atomic_set(&dma_ch[channel].chan_status, 0);
198
199 pr_debug("freedma() : END\n");
200}
201EXPORT_SYMBOL(free_dma);
202
203#ifdef CONFIG_PM
204# ifndef MAX_DMA_SUSPEND_CHANNELS
205# define MAX_DMA_SUSPEND_CHANNELS MAX_DMA_CHANNELS
206# endif
207int blackfin_dma_suspend(void)
208{
209 int i;
210
211 for (i = 0; i < MAX_DMA_CHANNELS; ++i) {
212 if (dma_ch[i].regs->cfg & DMAEN) {
213 printk(KERN_ERR "DMA Channel %d failed to suspend\n", i);
214 return -EBUSY;
215 }
216
217 if (i < MAX_DMA_SUSPEND_CHANNELS)
218 dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map;
219 }
220
221 return 0;
222}
223
224void blackfin_dma_resume(void)
225{
226 int i;
227
228 for (i = 0; i < MAX_DMA_CHANNELS; ++i) {
229 dma_ch[i].regs->cfg = 0;
230
231 if (i < MAX_DMA_SUSPEND_CHANNELS)
232 dma_ch[i].regs->peripheral_map = dma_ch[i].saved_peripheral_map;
233 }
234}
235#endif
236
237/**
238 * blackfin_dma_early_init - minimal DMA init
239 *
240 * Setup a few DMA registers so we can safely do DMA transfers early on in
241 * the kernel booting process. Really this just means using dma_memcpy().
242 */
243void __init blackfin_dma_early_init(void)
244{
245 early_shadow_stamp();
246 bfin_write_MDMA_S0_CONFIG(0);
247 bfin_write_MDMA_S1_CONFIG(0);
248}
249
250void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size)
251{
252 unsigned long dst = (unsigned long)pdst;
253 unsigned long src = (unsigned long)psrc;
254 struct dma_register *dst_ch, *src_ch;
255
256 early_shadow_stamp();
257
258 /* We assume that everything is 4 byte aligned, so include
259 * a basic sanity check
260 */
261 BUG_ON(dst % 4);
262 BUG_ON(src % 4);
263 BUG_ON(size % 4);
264
265 src_ch = 0;
266 /* Find an avalible memDMA channel */
267 while (1) {
268 if (src_ch == (struct dma_register *)MDMA_S0_NEXT_DESC_PTR) {
269 dst_ch = (struct dma_register *)MDMA_D1_NEXT_DESC_PTR;
270 src_ch = (struct dma_register *)MDMA_S1_NEXT_DESC_PTR;
271 } else {
272 dst_ch = (struct dma_register *)MDMA_D0_NEXT_DESC_PTR;
273 src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR;
274 }
275
276 if (!bfin_read16(&src_ch->cfg))
277 break;
278 else if (bfin_read16(&dst_ch->irq_status) & DMA_DONE) {
279 bfin_write16(&src_ch->cfg, 0);
280 break;
281 }
282 }
283
284 /* Force a sync in case a previous config reset on this channel
285 * occurred. This is needed so subsequent writes to DMA registers
286 * are not spuriously lost/corrupted.
287 */
288 __builtin_bfin_ssync();
289
290 /* Destination */
291 bfin_write32(&dst_ch->start_addr, dst);
292 bfin_write16(&dst_ch->x_count, size >> 2);
293 bfin_write16(&dst_ch->x_modify, 1 << 2);
294 bfin_write16(&dst_ch->irq_status, DMA_DONE | DMA_ERR);
295
296 /* Source */
297 bfin_write32(&src_ch->start_addr, src);
298 bfin_write16(&src_ch->x_count, size >> 2);
299 bfin_write16(&src_ch->x_modify, 1 << 2);
300 bfin_write16(&src_ch->irq_status, DMA_DONE | DMA_ERR);
301
302 /* Enable */
303 bfin_write16(&src_ch->cfg, DMAEN | WDSIZE_32);
304 bfin_write16(&dst_ch->cfg, WNR | DI_EN | DMAEN | WDSIZE_32);
305
306 /* Since we are atomic now, don't use the workaround ssync */
307 __builtin_bfin_ssync();
308}
309
310void __init early_dma_memcpy_done(void)
311{
312 early_shadow_stamp();
313
314 while ((bfin_read_MDMA_S0_CONFIG() && !(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) ||
315 (bfin_read_MDMA_S1_CONFIG() && !(bfin_read_MDMA_D1_IRQ_STATUS() & DMA_DONE)))
316 continue;
317
318 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
319 bfin_write_MDMA_D1_IRQ_STATUS(DMA_DONE | DMA_ERR);
320 /*
321 * Now that DMA is done, we would normally flush cache, but
322 * i/d cache isn't running this early, so we don't bother,
323 * and just clear out the DMA channel for next time
324 */
325 bfin_write_MDMA_S0_CONFIG(0);
326 bfin_write_MDMA_S1_CONFIG(0);
327 bfin_write_MDMA_D0_CONFIG(0);
328 bfin_write_MDMA_D1_CONFIG(0);
329
330 __builtin_bfin_ssync();
331}
332
333/**
334 * __dma_memcpy - program the MDMA registers
335 *
336 * Actually program MDMA0 and wait for the transfer to finish. Disable IRQs
337 * while programming registers so that everything is fully configured. Wait
338 * for DMA to finish with IRQs enabled. If interrupted, the initial DMA_DONE
339 * check will make sure we don't clobber any existing transfer.
340 */
341static void __dma_memcpy(u32 daddr, s16 dmod, u32 saddr, s16 smod, size_t cnt, u32 conf)
342{
343 static DEFINE_SPINLOCK(mdma_lock);
344 unsigned long flags;
345
346 spin_lock_irqsave(&mdma_lock, flags);
347
348 /* Force a sync in case a previous config reset on this channel
349 * occurred. This is needed so subsequent writes to DMA registers
350 * are not spuriously lost/corrupted. Do it under irq lock and
351 * without the anomaly version (because we are atomic already).
352 */
353 __builtin_bfin_ssync();
354
355 if (bfin_read_MDMA_S0_CONFIG())
356 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
357 continue;
358
359 if (conf & DMA2D) {
360 /* For larger bit sizes, we've already divided down cnt so it
361 * is no longer a multiple of 64k. So we have to break down
362 * the limit here so it is a multiple of the incoming size.
363 * There is no limitation here in terms of total size other
364 * than the hardware though as the bits lost in the shift are
365 * made up by MODIFY (== we can hit the whole address space).
366 * X: (2^(16 - 0)) * 1 == (2^(16 - 1)) * 2 == (2^(16 - 2)) * 4
367 */
368 u32 shift = abs(dmod) >> 1;
369 size_t ycnt = cnt >> (16 - shift);
370 cnt = 1 << (16 - shift);
371 bfin_write_MDMA_D0_Y_COUNT(ycnt);
372 bfin_write_MDMA_S0_Y_COUNT(ycnt);
373 bfin_write_MDMA_D0_Y_MODIFY(dmod);
374 bfin_write_MDMA_S0_Y_MODIFY(smod);
375 }
376
377 bfin_write_MDMA_D0_START_ADDR(daddr);
378 bfin_write_MDMA_D0_X_COUNT(cnt);
379 bfin_write_MDMA_D0_X_MODIFY(dmod);
380 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
381
382 bfin_write_MDMA_S0_START_ADDR(saddr);
383 bfin_write_MDMA_S0_X_COUNT(cnt);
384 bfin_write_MDMA_S0_X_MODIFY(smod);
385 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
386
387 bfin_write_MDMA_S0_CONFIG(DMAEN | conf);
388 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | conf);
389
390 spin_unlock_irqrestore(&mdma_lock, flags);
391
392 SSYNC();
393
394 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
395 if (bfin_read_MDMA_S0_CONFIG())
396 continue;
397 else
398 return;
399
400 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
401
402 bfin_write_MDMA_S0_CONFIG(0);
403 bfin_write_MDMA_D0_CONFIG(0);
404}
405
406/**
407 * _dma_memcpy - translate C memcpy settings into MDMA settings
408 *
409 * Handle all the high level steps before we touch the MDMA registers. So
410 * handle direction, tweaking of sizes, and formatting of addresses.
411 */
412static void *_dma_memcpy(void *pdst, const void *psrc, size_t size)
413{
414 u32 conf, shift;
415 s16 mod;
416 unsigned long dst = (unsigned long)pdst;
417 unsigned long src = (unsigned long)psrc;
418
419 if (size == 0)
420 return NULL;
421
422 if (dst % 4 == 0 && src % 4 == 0 && size % 4 == 0) {
423 conf = WDSIZE_32;
424 shift = 2;
425 } else if (dst % 2 == 0 && src % 2 == 0 && size % 2 == 0) {
426 conf = WDSIZE_16;
427 shift = 1;
428 } else {
429 conf = WDSIZE_8;
430 shift = 0;
431 }
432
433 /* If the two memory regions have a chance of overlapping, make
434 * sure the memcpy still works as expected. Do this by having the
435 * copy run backwards instead.
436 */
437 mod = 1 << shift;
438 if (src < dst) {
439 mod *= -1;
440 dst += size + mod;
441 src += size + mod;
442 }
443 size >>= shift;
444
445 if (size > 0x10000)
446 conf |= DMA2D;
447
448 __dma_memcpy(dst, mod, src, mod, size, conf);
449
450 return pdst;
451}
452
453/**
454 * dma_memcpy - DMA memcpy under mutex lock
455 *
456 * Do not check arguments before starting the DMA memcpy. Break the transfer
457 * up into two pieces. The first transfer is in multiples of 64k and the
458 * second transfer is the piece smaller than 64k.
459 */
460void *dma_memcpy(void *pdst, const void *psrc, size_t size)
461{
462 unsigned long dst = (unsigned long)pdst;
463 unsigned long src = (unsigned long)psrc;
464
465 if (bfin_addr_dcacheable(src))
466 blackfin_dcache_flush_range(src, src + size);
467
468 if (bfin_addr_dcacheable(dst))
469 blackfin_dcache_invalidate_range(dst, dst + size);
470
471 return dma_memcpy_nocache(pdst, psrc, size);
472}
473EXPORT_SYMBOL(dma_memcpy);
474
475/**
476 * dma_memcpy_nocache - DMA memcpy under mutex lock
477 * - No cache flush/invalidate
478 *
479 * Do not check arguments before starting the DMA memcpy. Break the transfer
480 * up into two pieces. The first transfer is in multiples of 64k and the
481 * second transfer is the piece smaller than 64k.
482 */
483void *dma_memcpy_nocache(void *pdst, const void *psrc, size_t size)
484{
485 size_t bulk, rest;
486
487 bulk = size & ~0xffff;
488 rest = size - bulk;
489 if (bulk)
490 _dma_memcpy(pdst, psrc, bulk);
491 _dma_memcpy(pdst + bulk, psrc + bulk, rest);
492 return pdst;
493}
494EXPORT_SYMBOL(dma_memcpy_nocache);
495
496/**
497 * safe_dma_memcpy - DMA memcpy w/argument checking
498 *
499 * Verify arguments are safe before heading to dma_memcpy().
500 */
501void *safe_dma_memcpy(void *dst, const void *src, size_t size)
502{
503 if (!access_ok(VERIFY_WRITE, dst, size))
504 return NULL;
505 if (!access_ok(VERIFY_READ, src, size))
506 return NULL;
507 return dma_memcpy(dst, src, size);
508}
509EXPORT_SYMBOL(safe_dma_memcpy);
510
511static void _dma_out(unsigned long addr, unsigned long buf, unsigned short len,
512 u16 size, u16 dma_size)
513{
514 blackfin_dcache_flush_range(buf, buf + len * size);
515 __dma_memcpy(addr, 0, buf, size, len, dma_size);
516}
517
518static void _dma_in(unsigned long addr, unsigned long buf, unsigned short len,
519 u16 size, u16 dma_size)
520{
521 blackfin_dcache_invalidate_range(buf, buf + len * size);
522 __dma_memcpy(buf, size, addr, 0, len, dma_size);
523}
524
525#define MAKE_DMA_IO(io, bwl, isize, dmasize, cnst) \
526void dma_##io##s##bwl(unsigned long addr, cnst void *buf, unsigned short len) \
527{ \
528 _dma_##io(addr, (unsigned long)buf, len, isize, WDSIZE_##dmasize); \
529} \
530EXPORT_SYMBOL(dma_##io##s##bwl)
531MAKE_DMA_IO(out, b, 1, 8, const);
532MAKE_DMA_IO(in, b, 1, 8, );
533MAKE_DMA_IO(out, w, 2, 16, const);
534MAKE_DMA_IO(in, w, 2, 16, );
535MAKE_DMA_IO(out, l, 4, 32, const);
536MAKE_DMA_IO(in, l, 4, 32, );
diff --git a/arch/blackfin/kernel/init_task.c b/arch/blackfin/kernel/init_task.c
new file mode 100644
index 00000000000..d3970e8acd1
--- /dev/null
+++ b/arch/blackfin/kernel/init_task.c
@@ -0,0 +1,32 @@
1/*
2 * Copyright 2004-2009 Analog Devices Inc.
3 *
4 * Licensed under the GPL-2 or later
5 */
6
7#include <linux/mm.h>
8#include <linux/module.h>
9#include <linux/init_task.h>
10#include <linux/mqueue.h>
11#include <linux/fs.h>
12
13static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
14static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
15/*
16 * Initial task structure.
17 *
18 * All other task structs will be allocated on slabs in fork.c
19 */
20struct task_struct init_task = INIT_TASK(init_task);
21EXPORT_SYMBOL(init_task);
22
23/*
24 * Initial thread structure.
25 *
26 * We need to make sure that this is 8192-byte aligned due to the
27 * way process stacks are handled. This is done by having a special
28 * "init_task" linker map entry.
29 */
30union thread_union init_thread_union
31 __init_task_data = {
32INIT_THREAD_INFO(init_task)};
diff --git a/arch/blackfin/kernel/pwm.c b/arch/blackfin/kernel/pwm.c
new file mode 100644
index 00000000000..33f5942733b
--- /dev/null
+++ b/arch/blackfin/kernel/pwm.c
@@ -0,0 +1,100 @@
1/*
2 * Blackfin Pulse Width Modulation (PWM) core
3 *
4 * Copyright (c) 2011 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/module.h>
10#include <linux/pwm.h>
11#include <linux/slab.h>
12
13#include <asm/gptimers.h>
14#include <asm/portmux.h>
15
16struct pwm_device {
17 unsigned id;
18 unsigned short pin;
19};
20
21static const unsigned short pwm_to_gptimer_per[] = {
22 P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR4, P_TMR5,
23 P_TMR6, P_TMR7, P_TMR8, P_TMR9, P_TMR10, P_TMR11,
24};
25
26struct pwm_device *pwm_request(int pwm_id, const char *label)
27{
28 struct pwm_device *pwm;
29 int ret;
30
31 /* XXX: pwm_id really should be unsigned */
32 if (pwm_id < 0)
33 return NULL;
34
35 pwm = kzalloc(sizeof(*pwm), GFP_KERNEL);
36 if (!pwm)
37 return pwm;
38
39 pwm->id = pwm_id;
40 if (pwm->id >= ARRAY_SIZE(pwm_to_gptimer_per))
41 goto err;
42
43 pwm->pin = pwm_to_gptimer_per[pwm->id];
44 ret = peripheral_request(pwm->pin, label);
45 if (ret)
46 goto err;
47
48 return pwm;
49 err:
50 kfree(pwm);
51 return NULL;
52}
53EXPORT_SYMBOL(pwm_request);
54
55void pwm_free(struct pwm_device *pwm)
56{
57 peripheral_free(pwm->pin);
58 kfree(pwm);
59}
60EXPORT_SYMBOL(pwm_free);
61
62int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
63{
64 unsigned long period, duty;
65 unsigned long long val;
66
67 if (duty_ns < 0 || duty_ns > period_ns)
68 return -EINVAL;
69
70 val = (unsigned long long)get_sclk() * period_ns;
71 do_div(val, NSEC_PER_SEC);
72 period = val;
73
74 val = (unsigned long long)period * duty_ns;
75 do_div(val, period_ns);
76 duty = period - val;
77
78 if (duty >= period)
79 duty = period - 1;
80
81 set_gptimer_config(pwm->id, TIMER_MODE_PWM | TIMER_PERIOD_CNT);
82 set_gptimer_pwidth(pwm->id, duty);
83 set_gptimer_period(pwm->id, period);
84
85 return 0;
86}
87EXPORT_SYMBOL(pwm_config);
88
89int pwm_enable(struct pwm_device *pwm)
90{
91 enable_gptimer(pwm->id);
92 return 0;
93}
94EXPORT_SYMBOL(pwm_enable);
95
96void pwm_disable(struct pwm_device *pwm)
97{
98 disable_gptimer(pwm->id);
99}
100EXPORT_SYMBOL(pwm_disable);