Commit 971d9e07e18fa3684e7fbc932f01aa2a0682f232
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge tag 'cris-changes-for-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/jesper/cris
Pull arch/chris updates from Jesper Nilsson: "Mostly cleanup and build fixes for CRISv32 allmodconfig God Jul och Gott Nytt år!" * tag 'cris-changes-for-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/jesper/cris: CRISv32: Remove last remnants of ETRAX_SPI_MMC_BOARD CRISv32: ETRAXFS: Fix recursive spinlock CRISv32: Select MTDRAM for axisflashmap CRISv32: Implement early console CRIS: Use KALLSYMs if available in call stack dump CRISv32: Fix declaration mismatch CRISv32: Rewrite of synchronous serial port driver CRIS: Update init memory handling CRISv32: Better handling of watchdog bite CRIS: Export missing function symbols CRIS: Export ioremap_nocache CRIS: Fix headers_install CRISv32: Add missing include for mm.h CRISv32: Drop obsolete file for SPI driver
Showing 17 changed files Side-by-side Diff
- arch/cris/arch-v10/lib/usercopy.c
- arch/cris/arch-v32/drivers/Kconfig
- arch/cris/arch-v32/drivers/Makefile
- arch/cris/arch-v32/drivers/i2c.h
- arch/cris/arch-v32/drivers/sync_serial.c
- arch/cris/arch-v32/kernel/debugport.c
- arch/cris/arch-v32/kernel/time.c
- arch/cris/arch-v32/lib/usercopy.c
- arch/cris/arch-v32/mach-fs/pinmux.c
- arch/cris/include/arch-v32/mach-fs/mach/pinmux.h
- arch/cris/include/asm/Kbuild
- arch/cris/include/uapi/asm/Kbuild
- arch/cris/kernel/crisksyms.c
- arch/cris/kernel/traps.c
- arch/cris/mm/init.c
- arch/cris/mm/ioremap.c
- scripts/headers.sh
arch/cris/arch-v10/lib/usercopy.c
... | ... | @@ -30,8 +30,7 @@ |
30 | 30 | /* Copy to userspace. This is based on the memcpy used for |
31 | 31 | kernel-to-kernel copying; see "string.c". */ |
32 | 32 | |
33 | -unsigned long | |
34 | -__copy_user (void __user *pdst, const void *psrc, unsigned long pn) | |
33 | +unsigned long __copy_user(void __user *pdst, const void *psrc, unsigned long pn) | |
35 | 34 | { |
36 | 35 | /* We want the parameters put in special registers. |
37 | 36 | Make sure the compiler is able to make something useful of this. |
38 | 37 | |
... | ... | @@ -187,13 +186,14 @@ |
187 | 186 | |
188 | 187 | return retn; |
189 | 188 | } |
189 | +EXPORT_SYMBOL(__copy_user); | |
190 | 190 | |
191 | 191 | /* Copy from user to kernel, zeroing the bytes that were inaccessible in |
192 | 192 | userland. The return-value is the number of bytes that were |
193 | 193 | inaccessible. */ |
194 | 194 | |
195 | -unsigned long | |
196 | -__copy_user_zeroing(void *pdst, const void __user *psrc, unsigned long pn) | |
195 | +unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, | |
196 | + unsigned long pn) | |
197 | 197 | { |
198 | 198 | /* We want the parameters put in special registers. |
199 | 199 | Make sure the compiler is able to make something useful of this. |
200 | 200 | |
... | ... | @@ -369,11 +369,10 @@ |
369 | 369 | |
370 | 370 | return retn + n; |
371 | 371 | } |
372 | +EXPORT_SYMBOL(__copy_user_zeroing); | |
372 | 373 | |
373 | 374 | /* Zero userspace. */ |
374 | - | |
375 | -unsigned long | |
376 | -__do_clear_user (void __user *pto, unsigned long pn) | |
375 | +unsigned long __do_clear_user(void __user *pto, unsigned long pn) | |
377 | 376 | { |
378 | 377 | /* We want the parameters put in special registers. |
379 | 378 | Make sure the compiler is able to make something useful of this. |
... | ... | @@ -521,4 +520,5 @@ |
521 | 520 | |
522 | 521 | return retn; |
523 | 522 | } |
523 | +EXPORT_SYMBOL(__do_clear_user); |
arch/cris/arch-v32/drivers/Kconfig
... | ... | @@ -108,6 +108,7 @@ |
108 | 108 | select MTD_JEDECPROBE |
109 | 109 | select MTD_BLOCK |
110 | 110 | select MTD_COMPLEX_MAPPINGS |
111 | + select MTD_MTDRAM | |
111 | 112 | help |
112 | 113 | This option enables MTD mapping of flash devices. Needed to use |
113 | 114 | flash memories. If unsure, say Y. |
... | ... | @@ -358,13 +359,6 @@ |
358 | 359 | default MMC |
359 | 360 | select SPI |
360 | 361 | select MMC_SPI |
361 | - select ETRAX_SPI_MMC_BOARD | |
362 | - | |
363 | -# For the parts that can't be a module (due to restrictions in | |
364 | -# framework elsewhere). | |
365 | -config ETRAX_SPI_MMC_BOARD | |
366 | - boolean | |
367 | - default n | |
368 | 362 | |
369 | 363 | # While the board info is MMC_SPI only, the drivers are written to be |
370 | 364 | # independent of MMC_SPI, so we'll keep SPI non-dependent on the |
arch/cris/arch-v32/drivers/Makefile
arch/cris/arch-v32/drivers/i2c.h
... | ... | @@ -2,7 +2,6 @@ |
2 | 2 | #include <linux/init.h> |
3 | 3 | |
4 | 4 | /* High level I2C actions */ |
5 | -int __init i2c_init(void); | |
6 | 5 | int i2c_write(unsigned char theSlave, void *data, size_t nbytes); |
7 | 6 | int i2c_read(unsigned char theSlave, void *data, size_t nbytes); |
8 | 7 | int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue); |
arch/cris/arch-v32/drivers/sync_serial.c
Changes suppressed. Click to show
1 | 1 | /* |
2 | - * Simple synchronous serial port driver for ETRAX FS and Artpec-3. | |
2 | + * Simple synchronous serial port driver for ETRAX FS and ARTPEC-3. | |
3 | 3 | * |
4 | - * Copyright (c) 2005 Axis Communications AB | |
5 | - * | |
4 | + * Copyright (c) 2005, 2008 Axis Communications AB | |
6 | 5 | * Author: Mikael Starvik |
7 | 6 | * |
8 | 7 | */ |
9 | 8 | |
10 | 9 | |
... | ... | @@ -16,16 +15,17 @@ |
16 | 15 | #include <linux/mutex.h> |
17 | 16 | #include <linux/interrupt.h> |
18 | 17 | #include <linux/poll.h> |
19 | -#include <linux/init.h> | |
20 | -#include <linux/timer.h> | |
21 | -#include <linux/spinlock.h> | |
18 | +#include <linux/fs.h> | |
19 | +#include <linux/cdev.h> | |
20 | +#include <linux/device.h> | |
22 | 21 | #include <linux/wait.h> |
23 | 22 | |
24 | 23 | #include <asm/io.h> |
25 | -#include <dma.h> | |
24 | +#include <mach/dma.h> | |
26 | 25 | #include <pinmux.h> |
27 | 26 | #include <hwregs/reg_rdwr.h> |
28 | 27 | #include <hwregs/sser_defs.h> |
28 | +#include <hwregs/timer_defs.h> | |
29 | 29 | #include <hwregs/dma_defs.h> |
30 | 30 | #include <hwregs/dma.h> |
31 | 31 | #include <hwregs/intr_vect_defs.h> |
32 | 32 | |
33 | 33 | |
34 | 34 | |
35 | 35 | |
36 | 36 | |
... | ... | @@ -59,22 +59,23 @@ |
59 | 59 | /* the rest of the data pointed out by Descr1 and set readp to the start */ |
60 | 60 | /* of Descr2 */ |
61 | 61 | |
62 | -#define SYNC_SERIAL_MAJOR 125 | |
63 | - | |
64 | 62 | /* IN_BUFFER_SIZE should be a multiple of 6 to make sure that 24 bit */ |
65 | 63 | /* words can be handled */ |
66 | -#define IN_BUFFER_SIZE 12288 | |
67 | -#define IN_DESCR_SIZE 256 | |
68 | -#define NBR_IN_DESCR (IN_BUFFER_SIZE/IN_DESCR_SIZE) | |
64 | +#define IN_DESCR_SIZE SSP_INPUT_CHUNK_SIZE | |
65 | +#define NBR_IN_DESCR (8*6) | |
66 | +#define IN_BUFFER_SIZE (IN_DESCR_SIZE * NBR_IN_DESCR) | |
69 | 67 | |
70 | -#define OUT_BUFFER_SIZE 1024*8 | |
71 | 68 | #define NBR_OUT_DESCR 8 |
69 | +#define OUT_BUFFER_SIZE (1024 * NBR_OUT_DESCR) | |
72 | 70 | |
73 | 71 | #define DEFAULT_FRAME_RATE 0 |
74 | 72 | #define DEFAULT_WORD_RATE 7 |
75 | 73 | |
74 | +/* To be removed when we move to pure udev. */ | |
75 | +#define SYNC_SERIAL_MAJOR 125 | |
76 | + | |
76 | 77 | /* NOTE: Enabling some debug will likely cause overrun or underrun, |
77 | - * especially if manual mode is use. | |
78 | + * especially if manual mode is used. | |
78 | 79 | */ |
79 | 80 | #define DEBUG(x) |
80 | 81 | #define DEBUGREAD(x) |
81 | 82 | |
... | ... | @@ -85,12 +86,29 @@ |
85 | 86 | #define DEBUGTRDMA(x) |
86 | 87 | #define DEBUGOUTBUF(x) |
87 | 88 | |
88 | -typedef struct sync_port | |
89 | -{ | |
90 | - reg_scope_instances regi_sser; | |
91 | - reg_scope_instances regi_dmain; | |
92 | - reg_scope_instances regi_dmaout; | |
89 | +enum syncser_irq_setup { | |
90 | + no_irq_setup = 0, | |
91 | + dma_irq_setup = 1, | |
92 | + manual_irq_setup = 2, | |
93 | +}; | |
93 | 94 | |
95 | +struct sync_port { | |
96 | + unsigned long regi_sser; | |
97 | + unsigned long regi_dmain; | |
98 | + unsigned long regi_dmaout; | |
99 | + | |
100 | + /* Interrupt vectors. */ | |
101 | + unsigned long dma_in_intr_vect; /* Used for DMA in. */ | |
102 | + unsigned long dma_out_intr_vect; /* Used for DMA out. */ | |
103 | + unsigned long syncser_intr_vect; /* Used when no DMA. */ | |
104 | + | |
105 | + /* DMA number for in and out. */ | |
106 | + unsigned int dma_in_nbr; | |
107 | + unsigned int dma_out_nbr; | |
108 | + | |
109 | + /* DMA owner. */ | |
110 | + enum dma_owner req_dma; | |
111 | + | |
94 | 112 | char started; /* 1 if port has been started */ |
95 | 113 | char port_nbr; /* Port 0 or 1 */ |
96 | 114 | char busy; /* 1 if port is busy */ |
97 | 115 | |
98 | 116 | |
99 | 117 | |
100 | 118 | |
101 | 119 | |
... | ... | @@ -99,23 +117,30 @@ |
99 | 117 | char use_dma; /* 1 if port uses dma */ |
100 | 118 | char tr_running; |
101 | 119 | |
102 | - char init_irqs; | |
120 | + enum syncser_irq_setup init_irqs; | |
103 | 121 | int output; |
104 | 122 | int input; |
105 | 123 | |
106 | 124 | /* Next byte to be read by application */ |
107 | - volatile unsigned char *volatile readp; | |
125 | + unsigned char *readp; | |
108 | 126 | /* Next byte to be written by etrax */ |
109 | - volatile unsigned char *volatile writep; | |
127 | + unsigned char *writep; | |
110 | 128 | |
111 | 129 | unsigned int in_buffer_size; |
130 | + unsigned int in_buffer_len; | |
112 | 131 | unsigned int inbufchunk; |
113 | - unsigned char out_buffer[OUT_BUFFER_SIZE] __attribute__ ((aligned(32))); | |
114 | - unsigned char in_buffer[IN_BUFFER_SIZE]__attribute__ ((aligned(32))); | |
115 | - unsigned char flip[IN_BUFFER_SIZE] __attribute__ ((aligned(32))); | |
116 | - struct dma_descr_data* next_rx_desc; | |
117 | - struct dma_descr_data* prev_rx_desc; | |
132 | + /* Data buffers for in and output. */ | |
133 | + unsigned char out_buffer[OUT_BUFFER_SIZE] __aligned(32); | |
134 | + unsigned char in_buffer[IN_BUFFER_SIZE] __aligned(32); | |
135 | + unsigned char flip[IN_BUFFER_SIZE] __aligned(32); | |
136 | + struct timespec timestamp[NBR_IN_DESCR]; | |
137 | + struct dma_descr_data *next_rx_desc; | |
138 | + struct dma_descr_data *prev_rx_desc; | |
118 | 139 | |
140 | + struct timeval last_timestamp; | |
141 | + int read_ts_idx; | |
142 | + int write_ts_idx; | |
143 | + | |
119 | 144 | /* Pointer to the first available descriptor in the ring, |
120 | 145 | * unless active_tr_descr == catch_tr_descr and a dma |
121 | 146 | * transfer is active */ |
122 | 147 | |
123 | 148 | |
124 | 149 | |
125 | 150 | |
126 | 151 | |
127 | 152 | |
128 | 153 | |
129 | 154 | |
130 | 155 | |
131 | 156 | |
132 | 157 | |
133 | 158 | |
134 | 159 | |
135 | 160 | |
136 | 161 | |
137 | 162 | |
138 | 163 | |
139 | 164 | |
140 | 165 | |
141 | 166 | |
... | ... | @@ -135,114 +160,138 @@ |
135 | 160 | /* Number of bytes currently locked for being read by DMA */ |
136 | 161 | int out_buf_count; |
137 | 162 | |
138 | - dma_descr_data in_descr[NBR_IN_DESCR] __attribute__ ((__aligned__(16))); | |
139 | - dma_descr_context in_context __attribute__ ((__aligned__(32))); | |
140 | - dma_descr_data out_descr[NBR_OUT_DESCR] | |
141 | - __attribute__ ((__aligned__(16))); | |
142 | - dma_descr_context out_context __attribute__ ((__aligned__(32))); | |
163 | + dma_descr_context in_context __aligned(32); | |
164 | + dma_descr_context out_context __aligned(32); | |
165 | + dma_descr_data in_descr[NBR_IN_DESCR] __aligned(16); | |
166 | + dma_descr_data out_descr[NBR_OUT_DESCR] __aligned(16); | |
167 | + | |
143 | 168 | wait_queue_head_t out_wait_q; |
144 | 169 | wait_queue_head_t in_wait_q; |
145 | 170 | |
146 | 171 | spinlock_t lock; |
147 | -} sync_port; | |
172 | +}; | |
148 | 173 | |
149 | 174 | static DEFINE_MUTEX(sync_serial_mutex); |
150 | 175 | static int etrax_sync_serial_init(void); |
151 | 176 | static void initialize_port(int portnbr); |
152 | 177 | static inline int sync_data_avail(struct sync_port *port); |
153 | 178 | |
154 | -static int sync_serial_open(struct inode *, struct file*); | |
155 | -static int sync_serial_release(struct inode*, struct file*); | |
179 | +static int sync_serial_open(struct inode *, struct file *); | |
180 | +static int sync_serial_release(struct inode *, struct file *); | |
156 | 181 | static unsigned int sync_serial_poll(struct file *filp, poll_table *wait); |
157 | 182 | |
158 | -static int sync_serial_ioctl(struct file *, | |
159 | - unsigned int cmd, unsigned long arg); | |
160 | -static ssize_t sync_serial_write(struct file * file, const char * buf, | |
183 | +static long sync_serial_ioctl(struct file *file, | |
184 | + unsigned int cmd, unsigned long arg); | |
185 | +static int sync_serial_ioctl_unlocked(struct file *file, | |
186 | + unsigned int cmd, unsigned long arg); | |
187 | +static ssize_t sync_serial_write(struct file *file, const char __user *buf, | |
161 | 188 | size_t count, loff_t *ppos); |
162 | -static ssize_t sync_serial_read(struct file *file, char *buf, | |
189 | +static ssize_t sync_serial_read(struct file *file, char __user *buf, | |
163 | 190 | size_t count, loff_t *ppos); |
164 | 191 | |
165 | -#if (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \ | |
166 | - defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)) || \ | |
167 | - (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) && \ | |
168 | - defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA)) | |
192 | +#if ((defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \ | |
193 | + defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)) || \ | |
194 | + (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) && \ | |
195 | + defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA))) | |
169 | 196 | #define SYNC_SER_DMA |
197 | +#else | |
198 | +#define SYNC_SER_MANUAL | |
170 | 199 | #endif |
171 | 200 | |
172 | -static void send_word(sync_port* port); | |
173 | -static void start_dma_out(struct sync_port *port, const char *data, int count); | |
174 | -static void start_dma_in(sync_port* port); | |
175 | 201 | #ifdef SYNC_SER_DMA |
202 | +static void start_dma_out(struct sync_port *port, const char *data, int count); | |
203 | +static void start_dma_in(struct sync_port *port); | |
176 | 204 | static irqreturn_t tr_interrupt(int irq, void *dev_id); |
177 | 205 | static irqreturn_t rx_interrupt(int irq, void *dev_id); |
178 | 206 | #endif |
179 | - | |
180 | -#if (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \ | |
181 | - !defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)) || \ | |
182 | - (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) && \ | |
183 | - !defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA)) | |
184 | -#define SYNC_SER_MANUAL | |
185 | -#endif | |
186 | 207 | #ifdef SYNC_SER_MANUAL |
208 | +static void send_word(struct sync_port *port); | |
187 | 209 | static irqreturn_t manual_interrupt(int irq, void *dev_id); |
188 | 210 | #endif |
189 | 211 | |
190 | -#ifdef CONFIG_ETRAXFS /* ETRAX FS */ | |
191 | -#define OUT_DMA_NBR 4 | |
192 | -#define IN_DMA_NBR 5 | |
193 | -#define PINMUX_SSER pinmux_sser0 | |
194 | -#define SYNCSER_INST regi_sser0 | |
195 | -#define SYNCSER_INTR_VECT SSER0_INTR_VECT | |
196 | -#define OUT_DMA_INST regi_dma4 | |
197 | -#define IN_DMA_INST regi_dma5 | |
198 | -#define DMA_OUT_INTR_VECT DMA4_INTR_VECT | |
199 | -#define DMA_IN_INTR_VECT DMA5_INTR_VECT | |
200 | -#define REQ_DMA_SYNCSER dma_sser0 | |
201 | -#else /* Artpec-3 */ | |
202 | -#define OUT_DMA_NBR 6 | |
203 | -#define IN_DMA_NBR 7 | |
204 | -#define PINMUX_SSER pinmux_sser | |
205 | -#define SYNCSER_INST regi_sser | |
206 | -#define SYNCSER_INTR_VECT SSER_INTR_VECT | |
207 | -#define OUT_DMA_INST regi_dma6 | |
208 | -#define IN_DMA_INST regi_dma7 | |
209 | -#define DMA_OUT_INTR_VECT DMA6_INTR_VECT | |
210 | -#define DMA_IN_INTR_VECT DMA7_INTR_VECT | |
211 | -#define REQ_DMA_SYNCSER dma_sser | |
212 | +#define artpec_pinmux_alloc_fixed crisv32_pinmux_alloc_fixed | |
213 | +#define artpec_request_dma crisv32_request_dma | |
214 | +#define artpec_free_dma crisv32_free_dma | |
215 | + | |
216 | +#ifdef CONFIG_ETRAXFS | |
217 | +/* ETRAX FS */ | |
218 | +#define DMA_OUT_NBR0 SYNC_SER0_TX_DMA_NBR | |
219 | +#define DMA_IN_NBR0 SYNC_SER0_RX_DMA_NBR | |
220 | +#define DMA_OUT_NBR1 SYNC_SER1_TX_DMA_NBR | |
221 | +#define DMA_IN_NBR1 SYNC_SER1_RX_DMA_NBR | |
222 | +#define PINMUX_SSER0 pinmux_sser0 | |
223 | +#define PINMUX_SSER1 pinmux_sser1 | |
224 | +#define SYNCSER_INST0 regi_sser0 | |
225 | +#define SYNCSER_INST1 regi_sser1 | |
226 | +#define SYNCSER_INTR_VECT0 SSER0_INTR_VECT | |
227 | +#define SYNCSER_INTR_VECT1 SSER1_INTR_VECT | |
228 | +#define OUT_DMA_INST0 regi_dma4 | |
229 | +#define IN_DMA_INST0 regi_dma5 | |
230 | +#define DMA_OUT_INTR_VECT0 DMA4_INTR_VECT | |
231 | +#define DMA_OUT_INTR_VECT1 DMA7_INTR_VECT | |
232 | +#define DMA_IN_INTR_VECT0 DMA5_INTR_VECT | |
233 | +#define DMA_IN_INTR_VECT1 DMA6_INTR_VECT | |
234 | +#define REQ_DMA_SYNCSER0 dma_sser0 | |
235 | +#define REQ_DMA_SYNCSER1 dma_sser1 | |
236 | +#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA) | |
237 | +#define PORT1_DMA 1 | |
238 | +#else | |
239 | +#define PORT1_DMA 0 | |
212 | 240 | #endif |
241 | +#elif defined(CONFIG_CRIS_MACH_ARTPEC3) | |
242 | +/* ARTPEC-3 */ | |
243 | +#define DMA_OUT_NBR0 SYNC_SER_TX_DMA_NBR | |
244 | +#define DMA_IN_NBR0 SYNC_SER_RX_DMA_NBR | |
245 | +#define PINMUX_SSER0 pinmux_sser | |
246 | +#define SYNCSER_INST0 regi_sser | |
247 | +#define SYNCSER_INTR_VECT0 SSER_INTR_VECT | |
248 | +#define OUT_DMA_INST0 regi_dma6 | |
249 | +#define IN_DMA_INST0 regi_dma7 | |
250 | +#define DMA_OUT_INTR_VECT0 DMA6_INTR_VECT | |
251 | +#define DMA_IN_INTR_VECT0 DMA7_INTR_VECT | |
252 | +#define REQ_DMA_SYNCSER0 dma_sser | |
253 | +#define REQ_DMA_SYNCSER1 dma_sser | |
254 | +#endif | |
213 | 255 | |
214 | -/* The ports */ | |
215 | -static struct sync_port ports[]= | |
216 | -{ | |
217 | - { | |
218 | - .regi_sser = SYNCSER_INST, | |
219 | - .regi_dmaout = OUT_DMA_INST, | |
220 | - .regi_dmain = IN_DMA_INST, | |
221 | 256 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA) |
222 | - .use_dma = 1, | |
257 | +#define PORT0_DMA 1 | |
223 | 258 | #else |
224 | - .use_dma = 0, | |
259 | +#define PORT0_DMA 0 | |
225 | 260 | #endif |
226 | - } | |
227 | -#ifdef CONFIG_ETRAXFS | |
228 | - , | |
229 | 261 | |
262 | +/* The ports */ | |
263 | +static struct sync_port ports[] = { | |
230 | 264 | { |
231 | - .regi_sser = regi_sser1, | |
232 | - .regi_dmaout = regi_dma6, | |
233 | - .regi_dmain = regi_dma7, | |
234 | -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA) | |
235 | - .use_dma = 1, | |
236 | -#else | |
237 | - .use_dma = 0, | |
265 | + .regi_sser = SYNCSER_INST0, | |
266 | + .regi_dmaout = OUT_DMA_INST0, | |
267 | + .regi_dmain = IN_DMA_INST0, | |
268 | + .use_dma = PORT0_DMA, | |
269 | + .dma_in_intr_vect = DMA_IN_INTR_VECT0, | |
270 | + .dma_out_intr_vect = DMA_OUT_INTR_VECT0, | |
271 | + .dma_in_nbr = DMA_IN_NBR0, | |
272 | + .dma_out_nbr = DMA_OUT_NBR0, | |
273 | + .req_dma = REQ_DMA_SYNCSER0, | |
274 | + .syncser_intr_vect = SYNCSER_INTR_VECT0, | |
275 | + }, | |
276 | +#ifdef CONFIG_ETRAXFS | |
277 | + { | |
278 | + .regi_sser = SYNCSER_INST1, | |
279 | + .regi_dmaout = regi_dma6, | |
280 | + .regi_dmain = regi_dma7, | |
281 | + .use_dma = PORT1_DMA, | |
282 | + .dma_in_intr_vect = DMA_IN_INTR_VECT1, | |
283 | + .dma_out_intr_vect = DMA_OUT_INTR_VECT1, | |
284 | + .dma_in_nbr = DMA_IN_NBR1, | |
285 | + .dma_out_nbr = DMA_OUT_NBR1, | |
286 | + .req_dma = REQ_DMA_SYNCSER1, | |
287 | + .syncser_intr_vect = SYNCSER_INTR_VECT1, | |
288 | + }, | |
238 | 289 | #endif |
239 | - } | |
240 | -#endif | |
241 | 290 | }; |
242 | 291 | |
243 | 292 | #define NBR_PORTS ARRAY_SIZE(ports) |
244 | 293 | |
245 | -static const struct file_operations sync_serial_fops = { | |
294 | +static const struct file_operations syncser_fops = { | |
246 | 295 | .owner = THIS_MODULE, |
247 | 296 | .write = sync_serial_write, |
248 | 297 | .read = sync_serial_read, |
249 | 298 | |
250 | 299 | |
251 | 300 | |
252 | 301 | |
253 | 302 | |
... | ... | @@ -253,61 +302,40 @@ |
253 | 302 | .llseek = noop_llseek, |
254 | 303 | }; |
255 | 304 | |
256 | -static int __init etrax_sync_serial_init(void) | |
257 | -{ | |
258 | - ports[0].enabled = 0; | |
259 | -#ifdef CONFIG_ETRAXFS | |
260 | - ports[1].enabled = 0; | |
261 | -#endif | |
262 | - if (register_chrdev(SYNC_SERIAL_MAJOR, "sync serial", | |
263 | - &sync_serial_fops) < 0) { | |
264 | - printk(KERN_WARNING | |
265 | - "Unable to get major for synchronous serial port\n"); | |
266 | - return -EBUSY; | |
267 | - } | |
305 | +static dev_t syncser_first; | |
306 | +static int minor_count = NBR_PORTS; | |
307 | +#define SYNCSER_NAME "syncser" | |
308 | +static struct cdev *syncser_cdev; | |
309 | +static struct class *syncser_class; | |
268 | 310 | |
269 | - /* Initialize Ports */ | |
270 | -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) | |
271 | - if (crisv32_pinmux_alloc_fixed(PINMUX_SSER)) { | |
272 | - printk(KERN_WARNING | |
273 | - "Unable to alloc pins for synchronous serial port 0\n"); | |
274 | - return -EIO; | |
275 | - } | |
276 | - ports[0].enabled = 1; | |
277 | - initialize_port(0); | |
278 | -#endif | |
279 | - | |
280 | -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) | |
281 | - if (crisv32_pinmux_alloc_fixed(pinmux_sser1)) { | |
282 | - printk(KERN_WARNING | |
283 | - "Unable to alloc pins for synchronous serial port 0\n"); | |
284 | - return -EIO; | |
285 | - } | |
286 | - ports[1].enabled = 1; | |
287 | - initialize_port(1); | |
288 | -#endif | |
289 | - | |
290 | -#ifdef CONFIG_ETRAXFS | |
291 | - printk(KERN_INFO "ETRAX FS synchronous serial port driver\n"); | |
292 | -#else | |
293 | - printk(KERN_INFO "Artpec-3 synchronous serial port driver\n"); | |
294 | -#endif | |
295 | - return 0; | |
311 | +static void sync_serial_start_port(struct sync_port *port) | |
312 | +{ | |
313 | + reg_sser_rw_cfg cfg = REG_RD(sser, port->regi_sser, rw_cfg); | |
314 | + reg_sser_rw_tr_cfg tr_cfg = | |
315 | + REG_RD(sser, port->regi_sser, rw_tr_cfg); | |
316 | + reg_sser_rw_rec_cfg rec_cfg = | |
317 | + REG_RD(sser, port->regi_sser, rw_rec_cfg); | |
318 | + cfg.en = regk_sser_yes; | |
319 | + tr_cfg.tr_en = regk_sser_yes; | |
320 | + rec_cfg.rec_en = regk_sser_yes; | |
321 | + REG_WR(sser, port->regi_sser, rw_cfg, cfg); | |
322 | + REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg); | |
323 | + REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg); | |
324 | + port->started = 1; | |
296 | 325 | } |
297 | 326 | |
298 | 327 | static void __init initialize_port(int portnbr) |
299 | 328 | { |
300 | - int __attribute__((unused)) i; | |
301 | 329 | struct sync_port *port = &ports[portnbr]; |
302 | - reg_sser_rw_cfg cfg = {0}; | |
303 | - reg_sser_rw_frm_cfg frm_cfg = {0}; | |
304 | - reg_sser_rw_tr_cfg tr_cfg = {0}; | |
305 | - reg_sser_rw_rec_cfg rec_cfg = {0}; | |
330 | + reg_sser_rw_cfg cfg = { 0 }; | |
331 | + reg_sser_rw_frm_cfg frm_cfg = { 0 }; | |
332 | + reg_sser_rw_tr_cfg tr_cfg = { 0 }; | |
333 | + reg_sser_rw_rec_cfg rec_cfg = { 0 }; | |
306 | 334 | |
307 | - DEBUG(printk(KERN_DEBUG "Init sync serial port %d\n", portnbr)); | |
335 | + DEBUG(pr_info("Init sync serial port %d\n", portnbr)); | |
308 | 336 | |
309 | 337 | port->port_nbr = portnbr; |
310 | - port->init_irqs = 1; | |
338 | + port->init_irqs = no_irq_setup; | |
311 | 339 | |
312 | 340 | port->out_rd_ptr = port->out_buffer; |
313 | 341 | port->out_buf_count = 0; |
314 | 342 | |
315 | 343 | |
... | ... | @@ -318,11 +346,12 @@ |
318 | 346 | port->readp = port->flip; |
319 | 347 | port->writep = port->flip; |
320 | 348 | port->in_buffer_size = IN_BUFFER_SIZE; |
349 | + port->in_buffer_len = 0; | |
321 | 350 | port->inbufchunk = IN_DESCR_SIZE; |
322 | - port->next_rx_desc = &port->in_descr[0]; | |
323 | - port->prev_rx_desc = &port->in_descr[NBR_IN_DESCR-1]; | |
324 | - port->prev_rx_desc->eol = 1; | |
325 | 351 | |
352 | + port->read_ts_idx = 0; | |
353 | + port->write_ts_idx = 0; | |
354 | + | |
326 | 355 | init_waitqueue_head(&port->out_wait_q); |
327 | 356 | init_waitqueue_head(&port->in_wait_q); |
328 | 357 | |
... | ... | @@ -368,14 +397,18 @@ |
368 | 397 | REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg); |
369 | 398 | |
370 | 399 | #ifdef SYNC_SER_DMA |
371 | - /* Setup the descriptor ring for dma out/transmit. */ | |
372 | - for (i = 0; i < NBR_OUT_DESCR; i++) { | |
373 | - port->out_descr[i].wait = 0; | |
374 | - port->out_descr[i].intr = 1; | |
375 | - port->out_descr[i].eol = 0; | |
376 | - port->out_descr[i].out_eop = 0; | |
377 | - port->out_descr[i].next = | |
378 | - (dma_descr_data *)virt_to_phys(&port->out_descr[i+1]); | |
400 | + { | |
401 | + int i; | |
402 | + /* Setup the descriptor ring for dma out/transmit. */ | |
403 | + for (i = 0; i < NBR_OUT_DESCR; i++) { | |
404 | + dma_descr_data *descr = &port->out_descr[i]; | |
405 | + descr->wait = 0; | |
406 | + descr->intr = 1; | |
407 | + descr->eol = 0; | |
408 | + descr->out_eop = 0; | |
409 | + descr->next = | |
410 | + (dma_descr_data *)virt_to_phys(&descr[i+1]); | |
411 | + } | |
379 | 412 | } |
380 | 413 | |
381 | 414 | /* Create a ring from the list. */ |
382 | 415 | |
383 | 416 | |
384 | 417 | |
385 | 418 | |
386 | 419 | |
387 | 420 | |
388 | 421 | |
389 | 422 | |
390 | 423 | |
391 | 424 | |
392 | 425 | |
393 | 426 | |
394 | 427 | |
395 | 428 | |
... | ... | @@ -391,201 +424,116 @@ |
391 | 424 | |
392 | 425 | static inline int sync_data_avail(struct sync_port *port) |
393 | 426 | { |
394 | - int avail; | |
395 | - unsigned char *start; | |
396 | - unsigned char *end; | |
397 | - | |
398 | - start = (unsigned char*)port->readp; /* cast away volatile */ | |
399 | - end = (unsigned char*)port->writep; /* cast away volatile */ | |
400 | - /* 0123456789 0123456789 | |
401 | - * ----- - ----- | |
402 | - * ^rp ^wp ^wp ^rp | |
403 | - */ | |
404 | - | |
405 | - if (end >= start) | |
406 | - avail = end - start; | |
407 | - else | |
408 | - avail = port->in_buffer_size - (start - end); | |
409 | - return avail; | |
427 | + return port->in_buffer_len; | |
410 | 428 | } |
411 | 429 | |
412 | -static inline int sync_data_avail_to_end(struct sync_port *port) | |
413 | -{ | |
414 | - int avail; | |
415 | - unsigned char *start; | |
416 | - unsigned char *end; | |
417 | - | |
418 | - start = (unsigned char*)port->readp; /* cast away volatile */ | |
419 | - end = (unsigned char*)port->writep; /* cast away volatile */ | |
420 | - /* 0123456789 0123456789 | |
421 | - * ----- ----- | |
422 | - * ^rp ^wp ^wp ^rp | |
423 | - */ | |
424 | - | |
425 | - if (end >= start) | |
426 | - avail = end - start; | |
427 | - else | |
428 | - avail = port->flip + port->in_buffer_size - start; | |
429 | - return avail; | |
430 | -} | |
431 | - | |
432 | 430 | static int sync_serial_open(struct inode *inode, struct file *file) |
433 | 431 | { |
432 | + int ret = 0; | |
434 | 433 | int dev = iminor(inode); |
435 | - int ret = -EBUSY; | |
436 | - sync_port *port; | |
437 | - reg_dma_rw_cfg cfg = {.en = regk_dma_yes}; | |
438 | - reg_dma_rw_intr_mask intr_mask = {.data = regk_dma_yes}; | |
434 | + struct sync_port *port; | |
435 | +#ifdef SYNC_SER_DMA | |
436 | + reg_dma_rw_cfg cfg = { .en = regk_dma_yes }; | |
437 | + reg_dma_rw_intr_mask intr_mask = { .data = regk_dma_yes }; | |
438 | +#endif | |
439 | 439 | |
440 | - mutex_lock(&sync_serial_mutex); | |
441 | - DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev)); | |
440 | + DEBUG(pr_debug("Open sync serial port %d\n", dev)); | |
442 | 441 | |
443 | - if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) | |
444 | - { | |
445 | - DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); | |
446 | - ret = -ENODEV; | |
447 | - goto out; | |
442 | + if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) { | |
443 | + DEBUG(pr_info("Invalid minor %d\n", dev)); | |
444 | + return -ENODEV; | |
448 | 445 | } |
449 | 446 | port = &ports[dev]; |
450 | 447 | /* Allow open this device twice (assuming one reader and one writer) */ |
451 | - if (port->busy == 2) | |
452 | - { | |
453 | - DEBUG(printk(KERN_DEBUG "Device is busy.. \n")); | |
454 | - goto out; | |
448 | + if (port->busy == 2) { | |
449 | + DEBUG(pr_info("syncser%d is busy\n", dev)); | |
450 | + return -EBUSY; | |
455 | 451 | } |
456 | 452 | |
453 | + mutex_lock(&sync_serial_mutex); | |
457 | 454 | |
458 | - if (port->init_irqs) { | |
459 | - if (port->use_dma) { | |
460 | - if (port == &ports[0]) { | |
455 | + /* Clear any stale date left in the flip buffer */ | |
456 | + port->readp = port->writep = port->flip; | |
457 | + port->in_buffer_len = 0; | |
458 | + port->read_ts_idx = 0; | |
459 | + port->write_ts_idx = 0; | |
460 | + | |
461 | + if (port->init_irqs != no_irq_setup) { | |
462 | + /* Init only on first call. */ | |
463 | + port->busy++; | |
464 | + mutex_unlock(&sync_serial_mutex); | |
465 | + return 0; | |
466 | + } | |
467 | + if (port->use_dma) { | |
461 | 468 | #ifdef SYNC_SER_DMA |
462 | - if (request_irq(DMA_OUT_INTR_VECT, | |
463 | - tr_interrupt, | |
464 | - 0, | |
465 | - "synchronous serial 0 dma tr", | |
466 | - &ports[0])) { | |
467 | - printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ"); | |
468 | - goto out; | |
469 | - } else if (request_irq(DMA_IN_INTR_VECT, | |
470 | - rx_interrupt, | |
471 | - 0, | |
472 | - "synchronous serial 1 dma rx", | |
473 | - &ports[0])) { | |
474 | - free_irq(DMA_OUT_INTR_VECT, &port[0]); | |
475 | - printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ"); | |
476 | - goto out; | |
477 | - } else if (crisv32_request_dma(OUT_DMA_NBR, | |
478 | - "synchronous serial 0 dma tr", | |
479 | - DMA_VERBOSE_ON_ERROR, | |
480 | - 0, | |
481 | - REQ_DMA_SYNCSER)) { | |
482 | - free_irq(DMA_OUT_INTR_VECT, &port[0]); | |
483 | - free_irq(DMA_IN_INTR_VECT, &port[0]); | |
484 | - printk(KERN_CRIT "Can't allocate sync serial port 0 TX DMA channel"); | |
485 | - goto out; | |
486 | - } else if (crisv32_request_dma(IN_DMA_NBR, | |
487 | - "synchronous serial 0 dma rec", | |
488 | - DMA_VERBOSE_ON_ERROR, | |
489 | - 0, | |
490 | - REQ_DMA_SYNCSER)) { | |
491 | - crisv32_free_dma(OUT_DMA_NBR); | |
492 | - free_irq(DMA_OUT_INTR_VECT, &port[0]); | |
493 | - free_irq(DMA_IN_INTR_VECT, &port[0]); | |
494 | - printk(KERN_CRIT "Can't allocate sync serial port 1 RX DMA channel"); | |
495 | - goto out; | |
496 | - } | |
497 | -#endif | |
498 | - } | |
499 | -#ifdef CONFIG_ETRAXFS | |
500 | - else if (port == &ports[1]) { | |
501 | -#ifdef SYNC_SER_DMA | |
502 | - if (request_irq(DMA6_INTR_VECT, | |
503 | - tr_interrupt, | |
504 | - 0, | |
505 | - "synchronous serial 1 dma tr", | |
506 | - &ports[1])) { | |
507 | - printk(KERN_CRIT "Can't allocate sync serial port 1 IRQ"); | |
508 | - goto out; | |
509 | - } else if (request_irq(DMA7_INTR_VECT, | |
510 | - rx_interrupt, | |
511 | - 0, | |
512 | - "synchronous serial 1 dma rx", | |
513 | - &ports[1])) { | |
514 | - free_irq(DMA6_INTR_VECT, &ports[1]); | |
515 | - printk(KERN_CRIT "Can't allocate sync serial port 3 IRQ"); | |
516 | - goto out; | |
517 | - } else if (crisv32_request_dma( | |
518 | - SYNC_SER1_TX_DMA_NBR, | |
519 | - "synchronous serial 1 dma tr", | |
520 | - DMA_VERBOSE_ON_ERROR, | |
521 | - 0, | |
522 | - dma_sser1)) { | |
523 | - free_irq(DMA6_INTR_VECT, &ports[1]); | |
524 | - free_irq(DMA7_INTR_VECT, &ports[1]); | |
525 | - printk(KERN_CRIT "Can't allocate sync serial port 3 TX DMA channel"); | |
526 | - goto out; | |
527 | - } else if (crisv32_request_dma( | |
528 | - SYNC_SER1_RX_DMA_NBR, | |
529 | - "synchronous serial 3 dma rec", | |
530 | - DMA_VERBOSE_ON_ERROR, | |
531 | - 0, | |
532 | - dma_sser1)) { | |
533 | - crisv32_free_dma(SYNC_SER1_TX_DMA_NBR); | |
534 | - free_irq(DMA6_INTR_VECT, &ports[1]); | |
535 | - free_irq(DMA7_INTR_VECT, &ports[1]); | |
536 | - printk(KERN_CRIT "Can't allocate sync serial port 3 RX DMA channel"); | |
537 | - goto out; | |
538 | - } | |
539 | -#endif | |
540 | - } | |
541 | -#endif | |
542 | - /* Enable DMAs */ | |
543 | - REG_WR(dma, port->regi_dmain, rw_cfg, cfg); | |
544 | - REG_WR(dma, port->regi_dmaout, rw_cfg, cfg); | |
545 | - /* Enable DMA IRQs */ | |
546 | - REG_WR(dma, port->regi_dmain, rw_intr_mask, intr_mask); | |
547 | - REG_WR(dma, port->regi_dmaout, rw_intr_mask, intr_mask); | |
548 | - /* Set up wordsize = 1 for DMAs. */ | |
549 | - DMA_WR_CMD (port->regi_dmain, regk_dma_set_w_size1); | |
550 | - DMA_WR_CMD (port->regi_dmaout, regk_dma_set_w_size1); | |
469 | + const char *tmp; | |
470 | + DEBUG(pr_info("Using DMA for syncser%d\n", dev)); | |
551 | 471 | |
552 | - start_dma_in(port); | |
553 | - port->init_irqs = 0; | |
554 | - } else { /* !port->use_dma */ | |
555 | -#ifdef SYNC_SER_MANUAL | |
556 | - if (port == &ports[0]) { | |
557 | - if (request_irq(SYNCSER_INTR_VECT, | |
558 | - manual_interrupt, | |
559 | - 0, | |
560 | - "synchronous serial manual irq", | |
561 | - &ports[0])) { | |
562 | - printk("Can't allocate sync serial manual irq"); | |
563 | - goto out; | |
564 | - } | |
565 | - } | |
566 | -#ifdef CONFIG_ETRAXFS | |
567 | - else if (port == &ports[1]) { | |
568 | - if (request_irq(SSER1_INTR_VECT, | |
569 | - manual_interrupt, | |
570 | - 0, | |
571 | - "synchronous serial manual irq", | |
572 | - &ports[1])) { | |
573 | - printk(KERN_CRIT "Can't allocate sync serial manual irq"); | |
574 | - goto out; | |
575 | - } | |
576 | - } | |
472 | + tmp = dev == 0 ? "syncser0 tx" : "syncser1 tx"; | |
473 | + if (request_irq(port->dma_out_intr_vect, tr_interrupt, 0, | |
474 | + tmp, port)) { | |
475 | + pr_err("Can't alloc syncser%d TX IRQ", dev); | |
476 | + ret = -EBUSY; | |
477 | + goto unlock_and_exit; | |
478 | + } | |
479 | + if (artpec_request_dma(port->dma_out_nbr, tmp, | |
480 | + DMA_VERBOSE_ON_ERROR, 0, port->req_dma)) { | |
481 | + free_irq(port->dma_out_intr_vect, port); | |
482 | + pr_err("Can't alloc syncser%d TX DMA", dev); | |
483 | + ret = -EBUSY; | |
484 | + goto unlock_and_exit; | |
485 | + } | |
486 | + tmp = dev == 0 ? "syncser0 rx" : "syncser1 rx"; | |
487 | + if (request_irq(port->dma_in_intr_vect, rx_interrupt, 0, | |
488 | + tmp, port)) { | |
489 | + artpec_free_dma(port->dma_out_nbr); | |
490 | + free_irq(port->dma_out_intr_vect, port); | |
491 | + pr_err("Can't alloc syncser%d RX IRQ", dev); | |
492 | + ret = -EBUSY; | |
493 | + goto unlock_and_exit; | |
494 | + } | |
495 | + if (artpec_request_dma(port->dma_in_nbr, tmp, | |
496 | + DMA_VERBOSE_ON_ERROR, 0, port->req_dma)) { | |
497 | + artpec_free_dma(port->dma_out_nbr); | |
498 | + free_irq(port->dma_out_intr_vect, port); | |
499 | + free_irq(port->dma_in_intr_vect, port); | |
500 | + pr_err("Can't alloc syncser%d RX DMA", dev); | |
501 | + ret = -EBUSY; | |
502 | + goto unlock_and_exit; | |
503 | + } | |
504 | + /* Enable DMAs */ | |
505 | + REG_WR(dma, port->regi_dmain, rw_cfg, cfg); | |
506 | + REG_WR(dma, port->regi_dmaout, rw_cfg, cfg); | |
507 | + /* Enable DMA IRQs */ | |
508 | + REG_WR(dma, port->regi_dmain, rw_intr_mask, intr_mask); | |
509 | + REG_WR(dma, port->regi_dmaout, rw_intr_mask, intr_mask); | |
510 | + /* Set up wordsize = 1 for DMAs. */ | |
511 | + DMA_WR_CMD(port->regi_dmain, regk_dma_set_w_size1); | |
512 | + DMA_WR_CMD(port->regi_dmaout, regk_dma_set_w_size1); | |
513 | + | |
514 | + start_dma_in(port); | |
515 | + port->init_irqs = dma_irq_setup; | |
577 | 516 | #endif |
578 | - port->init_irqs = 0; | |
517 | + } else { /* !port->use_dma */ | |
518 | +#ifdef SYNC_SER_MANUAL | |
519 | + const char *tmp = dev == 0 ? "syncser0 manual irq" : | |
520 | + "syncser1 manual irq"; | |
521 | + if (request_irq(port->syncser_intr_vect, manual_interrupt, | |
522 | + 0, tmp, port)) { | |
523 | + pr_err("Can't alloc syncser%d manual irq", | |
524 | + dev); | |
525 | + ret = -EBUSY; | |
526 | + goto unlock_and_exit; | |
527 | + } | |
528 | + port->init_irqs = manual_irq_setup; | |
579 | 529 | #else |
580 | - panic("sync_serial: Manual mode not supported.\n"); | |
530 | + panic("sync_serial: Manual mode not supported\n"); | |
581 | 531 | #endif /* SYNC_SER_MANUAL */ |
582 | - } | |
583 | - | |
584 | - } /* port->init_irqs */ | |
585 | - | |
532 | + } | |
586 | 533 | port->busy++; |
587 | 534 | ret = 0; |
588 | -out: | |
535 | + | |
536 | +unlock_and_exit: | |
589 | 537 | mutex_unlock(&sync_serial_mutex); |
590 | 538 | return ret; |
591 | 539 | } |
592 | 540 | |
593 | 541 | |
... | ... | @@ -593,18 +541,17 @@ |
593 | 541 | static int sync_serial_release(struct inode *inode, struct file *file) |
594 | 542 | { |
595 | 543 | int dev = iminor(inode); |
596 | - sync_port *port; | |
544 | + struct sync_port *port; | |
597 | 545 | |
598 | - if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) | |
599 | - { | |
600 | - DEBUG(printk("Invalid minor %d\n", dev)); | |
546 | + if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) { | |
547 | + DEBUG(pr_info("Invalid minor %d\n", dev)); | |
601 | 548 | return -ENODEV; |
602 | 549 | } |
603 | 550 | port = &ports[dev]; |
604 | 551 | if (port->busy) |
605 | 552 | port->busy--; |
606 | 553 | if (!port->busy) |
607 | - /* XXX */ ; | |
554 | + /* XXX */; | |
608 | 555 | return 0; |
609 | 556 | } |
610 | 557 | |
611 | 558 | |
... | ... | @@ -612,21 +559,15 @@ |
612 | 559 | { |
613 | 560 | int dev = iminor(file_inode(file)); |
614 | 561 | unsigned int mask = 0; |
615 | - sync_port *port; | |
616 | - DEBUGPOLL( static unsigned int prev_mask = 0; ); | |
562 | + struct sync_port *port; | |
563 | + DEBUGPOLL( | |
564 | + static unsigned int prev_mask; | |
565 | + ); | |
617 | 566 | |
618 | 567 | port = &ports[dev]; |
619 | 568 | |
620 | - if (!port->started) { | |
621 | - reg_sser_rw_cfg cfg = REG_RD(sser, port->regi_sser, rw_cfg); | |
622 | - reg_sser_rw_rec_cfg rec_cfg = | |
623 | - REG_RD(sser, port->regi_sser, rw_rec_cfg); | |
624 | - cfg.en = regk_sser_yes; | |
625 | - rec_cfg.rec_en = port->input; | |
626 | - REG_WR(sser, port->regi_sser, rw_cfg, cfg); | |
627 | - REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg); | |
628 | - port->started = 1; | |
629 | - } | |
569 | + if (!port->started) | |
570 | + sync_serial_start_port(port); | |
630 | 571 | |
631 | 572 | poll_wait(file, &port->out_wait_q, wait); |
632 | 573 | poll_wait(file, &port->in_wait_q, wait); |
633 | 574 | |
634 | 575 | |
635 | 576 | |
636 | 577 | |
637 | 578 | |
... | ... | @@ -645,33 +586,175 @@ |
645 | 586 | if (port->input && sync_data_avail(port) >= port->inbufchunk) |
646 | 587 | mask |= POLLIN | POLLRDNORM; |
647 | 588 | |
648 | - DEBUGPOLL(if (mask != prev_mask) | |
649 | - printk("sync_serial_poll: mask 0x%08X %s %s\n", mask, | |
650 | - mask&POLLOUT?"POLLOUT":"", mask&POLLIN?"POLLIN":""); | |
651 | - prev_mask = mask; | |
652 | - ); | |
589 | + DEBUGPOLL( | |
590 | + if (mask != prev_mask) | |
591 | + pr_info("sync_serial_poll: mask 0x%08X %s %s\n", | |
592 | + mask, | |
593 | + mask & POLLOUT ? "POLLOUT" : "", | |
594 | + mask & POLLIN ? "POLLIN" : ""); | |
595 | + prev_mask = mask; | |
596 | + ); | |
653 | 597 | return mask; |
654 | 598 | } |
655 | 599 | |
656 | -static int sync_serial_ioctl(struct file *file, | |
657 | - unsigned int cmd, unsigned long arg) | |
600 | +static ssize_t __sync_serial_read(struct file *file, | |
601 | + char __user *buf, | |
602 | + size_t count, | |
603 | + loff_t *ppos, | |
604 | + struct timespec *ts) | |
658 | 605 | { |
606 | + unsigned long flags; | |
607 | + int dev = MINOR(file->f_dentry->d_inode->i_rdev); | |
608 | + int avail; | |
609 | + struct sync_port *port; | |
610 | + unsigned char *start; | |
611 | + unsigned char *end; | |
612 | + | |
613 | + if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) { | |
614 | + DEBUG(pr_info("Invalid minor %d\n", dev)); | |
615 | + return -ENODEV; | |
616 | + } | |
617 | + port = &ports[dev]; | |
618 | + | |
619 | + if (!port->started) | |
620 | + sync_serial_start_port(port); | |
621 | + | |
622 | + /* Calculate number of available bytes */ | |
623 | + /* Save pointers to avoid that they are modified by interrupt */ | |
624 | + spin_lock_irqsave(&port->lock, flags); | |
625 | + start = port->readp; | |
626 | + end = port->writep; | |
627 | + spin_unlock_irqrestore(&port->lock, flags); | |
628 | + | |
629 | + while ((start == end) && !port->in_buffer_len) { | |
630 | + if (file->f_flags & O_NONBLOCK) | |
631 | + return -EAGAIN; | |
632 | + | |
633 | + wait_event_interruptible(port->in_wait_q, | |
634 | + !(start == end && !port->full)); | |
635 | + | |
636 | + if (signal_pending(current)) | |
637 | + return -EINTR; | |
638 | + | |
639 | + spin_lock_irqsave(&port->lock, flags); | |
640 | + start = port->readp; | |
641 | + end = port->writep; | |
642 | + spin_unlock_irqrestore(&port->lock, flags); | |
643 | + } | |
644 | + | |
645 | + DEBUGREAD(pr_info("R%d c %d ri %u wi %u /%u\n", | |
646 | + dev, count, | |
647 | + start - port->flip, end - port->flip, | |
648 | + port->in_buffer_size)); | |
649 | + | |
650 | + /* Lazy read, never return wrapped data. */ | |
651 | + if (end > start) | |
652 | + avail = end - start; | |
653 | + else | |
654 | + avail = port->flip + port->in_buffer_size - start; | |
655 | + | |
656 | + count = count > avail ? avail : count; | |
657 | + if (copy_to_user(buf, start, count)) | |
658 | + return -EFAULT; | |
659 | + | |
660 | + /* If timestamp requested, find timestamp of first returned byte | |
661 | + * and copy it. | |
662 | + * N.B: Applications that request timstamps MUST read data in | |
663 | + * chunks that are multiples of IN_DESCR_SIZE. | |
664 | + * Otherwise the timestamps will not be aligned to the data read. | |
665 | + */ | |
666 | + if (ts != NULL) { | |
667 | + int idx = port->read_ts_idx; | |
668 | + memcpy(ts, &port->timestamp[idx], sizeof(struct timespec)); | |
669 | + port->read_ts_idx += count / IN_DESCR_SIZE; | |
670 | + if (port->read_ts_idx >= NBR_IN_DESCR) | |
671 | + port->read_ts_idx = 0; | |
672 | + } | |
673 | + | |
674 | + spin_lock_irqsave(&port->lock, flags); | |
675 | + port->readp += count; | |
676 | + /* Check for wrap */ | |
677 | + if (port->readp >= port->flip + port->in_buffer_size) | |
678 | + port->readp = port->flip; | |
679 | + port->in_buffer_len -= count; | |
680 | + port->full = 0; | |
681 | + spin_unlock_irqrestore(&port->lock, flags); | |
682 | + | |
683 | + DEBUGREAD(pr_info("r %d\n", count)); | |
684 | + | |
685 | + return count; | |
686 | +} | |
687 | + | |
688 | +static ssize_t sync_serial_input(struct file *file, unsigned long arg) | |
689 | +{ | |
690 | + struct ssp_request req; | |
691 | + int count; | |
692 | + int ret; | |
693 | + | |
694 | + /* Copy the request structure from user-mode. */ | |
695 | + ret = copy_from_user(&req, (struct ssp_request __user *)arg, | |
696 | + sizeof(struct ssp_request)); | |
697 | + | |
698 | + if (ret) { | |
699 | + DEBUG(pr_info("sync_serial_input copy from user failed\n")); | |
700 | + return -EFAULT; | |
701 | + } | |
702 | + | |
703 | + /* To get the timestamps aligned, make sure that 'len' | |
704 | + * is a multiple of IN_DESCR_SIZE. | |
705 | + */ | |
706 | + if ((req.len % IN_DESCR_SIZE) != 0) { | |
707 | + DEBUG(pr_info("sync_serial: req.len %x, IN_DESCR_SIZE %x\n", | |
708 | + req.len, IN_DESCR_SIZE)); | |
709 | + return -EFAULT; | |
710 | + } | |
711 | + | |
712 | + /* Do the actual read. */ | |
713 | + /* Note that req.buf is actually a pointer to user space. */ | |
714 | + count = __sync_serial_read(file, req.buf, req.len, | |
715 | + NULL, &req.ts); | |
716 | + | |
717 | + if (count < 0) { | |
718 | + DEBUG(pr_info("sync_serial_input read failed\n")); | |
719 | + return count; | |
720 | + } | |
721 | + | |
722 | + /* Copy the request back to user-mode. */ | |
723 | + ret = copy_to_user((struct ssp_request __user *)arg, &req, | |
724 | + sizeof(struct ssp_request)); | |
725 | + | |
726 | + if (ret) { | |
727 | + DEBUG(pr_info("syncser input copy2user failed\n")); | |
728 | + return -EFAULT; | |
729 | + } | |
730 | + | |
731 | + /* Return the number of bytes read. */ | |
732 | + return count; | |
733 | +} | |
734 | + | |
735 | + | |
736 | +static int sync_serial_ioctl_unlocked(struct file *file, | |
737 | + unsigned int cmd, unsigned long arg) | |
738 | +{ | |
659 | 739 | int return_val = 0; |
660 | 740 | int dma_w_size = regk_dma_set_w_size1; |
661 | 741 | int dev = iminor(file_inode(file)); |
662 | - sync_port *port; | |
742 | + struct sync_port *port; | |
663 | 743 | reg_sser_rw_tr_cfg tr_cfg; |
664 | 744 | reg_sser_rw_rec_cfg rec_cfg; |
665 | 745 | reg_sser_rw_frm_cfg frm_cfg; |
666 | 746 | reg_sser_rw_cfg gen_cfg; |
667 | 747 | reg_sser_rw_intr_mask intr_mask; |
668 | 748 | |
669 | - if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) | |
670 | - { | |
671 | - DEBUG(printk("Invalid minor %d\n", dev)); | |
749 | + if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) { | |
750 | + DEBUG(pr_info("Invalid minor %d\n", dev)); | |
672 | 751 | return -1; |
673 | 752 | } |
674 | - port = &ports[dev]; | |
753 | + | |
754 | + if (cmd == SSP_INPUT) | |
755 | + return sync_serial_input(file, arg); | |
756 | + | |
757 | + port = &ports[dev]; | |
675 | 758 | spin_lock_irq(&port->lock); |
676 | 759 | |
677 | 760 | tr_cfg = REG_RD(sser, port->regi_sser, rw_tr_cfg); |
678 | 761 | |
... | ... | @@ -680,11 +763,9 @@ |
680 | 763 | gen_cfg = REG_RD(sser, port->regi_sser, rw_cfg); |
681 | 764 | intr_mask = REG_RD(sser, port->regi_sser, rw_intr_mask); |
682 | 765 | |
683 | - switch(cmd) | |
684 | - { | |
766 | + switch (cmd) { | |
685 | 767 | case SSP_SPEED: |
686 | - if (GET_SPEED(arg) == CODEC) | |
687 | - { | |
768 | + if (GET_SPEED(arg) == CODEC) { | |
688 | 769 | unsigned int freq; |
689 | 770 | |
690 | 771 | gen_cfg.base_freq = regk_sser_f32; |
691 | 772 | |
692 | 773 | |
693 | 774 | |
... | ... | @@ -701,16 +782,26 @@ |
701 | 782 | case FREQ_256kHz: |
702 | 783 | gen_cfg.clk_div = 125 * |
703 | 784 | (1 << (freq - FREQ_256kHz)) - 1; |
704 | - break; | |
785 | + break; | |
705 | 786 | case FREQ_512kHz: |
706 | 787 | gen_cfg.clk_div = 62; |
707 | - break; | |
788 | + break; | |
708 | 789 | case FREQ_1MHz: |
709 | 790 | case FREQ_2MHz: |
710 | 791 | case FREQ_4MHz: |
711 | 792 | gen_cfg.clk_div = 8 * (1 << freq) - 1; |
712 | - break; | |
793 | + break; | |
713 | 794 | } |
795 | + } else if (GET_SPEED(arg) == CODEC_f32768) { | |
796 | + gen_cfg.base_freq = regk_sser_f32_768; | |
797 | + switch (GET_FREQ(arg)) { | |
798 | + case FREQ_4096kHz: | |
799 | + gen_cfg.clk_div = 7; | |
800 | + break; | |
801 | + default: | |
802 | + spin_unlock_irq(&port->lock); | |
803 | + return -EINVAL; | |
804 | + } | |
714 | 805 | } else { |
715 | 806 | gen_cfg.base_freq = regk_sser_f29_493; |
716 | 807 | switch (GET_SPEED(arg)) { |
717 | 808 | |
718 | 809 | |
719 | 810 | |
... | ... | @@ -767,62 +858,64 @@ |
767 | 858 | |
768 | 859 | break; |
769 | 860 | case SSP_MODE: |
770 | - switch(arg) | |
771 | - { | |
772 | - case MASTER_OUTPUT: | |
773 | - port->output = 1; | |
774 | - port->input = 0; | |
775 | - frm_cfg.out_on = regk_sser_tr; | |
776 | - frm_cfg.frame_pin_dir = regk_sser_out; | |
777 | - gen_cfg.clk_dir = regk_sser_out; | |
778 | - break; | |
779 | - case SLAVE_OUTPUT: | |
780 | - port->output = 1; | |
781 | - port->input = 0; | |
782 | - frm_cfg.frame_pin_dir = regk_sser_in; | |
783 | - gen_cfg.clk_dir = regk_sser_in; | |
784 | - break; | |
785 | - case MASTER_INPUT: | |
786 | - port->output = 0; | |
787 | - port->input = 1; | |
788 | - frm_cfg.frame_pin_dir = regk_sser_out; | |
789 | - frm_cfg.out_on = regk_sser_intern_tb; | |
790 | - gen_cfg.clk_dir = regk_sser_out; | |
791 | - break; | |
792 | - case SLAVE_INPUT: | |
793 | - port->output = 0; | |
794 | - port->input = 1; | |
795 | - frm_cfg.frame_pin_dir = regk_sser_in; | |
796 | - gen_cfg.clk_dir = regk_sser_in; | |
797 | - break; | |
798 | - case MASTER_BIDIR: | |
799 | - port->output = 1; | |
800 | - port->input = 1; | |
801 | - frm_cfg.frame_pin_dir = regk_sser_out; | |
802 | - frm_cfg.out_on = regk_sser_intern_tb; | |
803 | - gen_cfg.clk_dir = regk_sser_out; | |
804 | - break; | |
805 | - case SLAVE_BIDIR: | |
806 | - port->output = 1; | |
807 | - port->input = 1; | |
808 | - frm_cfg.frame_pin_dir = regk_sser_in; | |
809 | - gen_cfg.clk_dir = regk_sser_in; | |
810 | - break; | |
811 | - default: | |
812 | - spin_unlock_irq(&port->lock); | |
813 | - return -EINVAL; | |
861 | + switch (arg) { | |
862 | + case MASTER_OUTPUT: | |
863 | + port->output = 1; | |
864 | + port->input = 0; | |
865 | + frm_cfg.out_on = regk_sser_tr; | |
866 | + frm_cfg.frame_pin_dir = regk_sser_out; | |
867 | + gen_cfg.clk_dir = regk_sser_out; | |
868 | + break; | |
869 | + case SLAVE_OUTPUT: | |
870 | + port->output = 1; | |
871 | + port->input = 0; | |
872 | + frm_cfg.frame_pin_dir = regk_sser_in; | |
873 | + gen_cfg.clk_dir = regk_sser_in; | |
874 | + break; | |
875 | + case MASTER_INPUT: | |
876 | + port->output = 0; | |
877 | + port->input = 1; | |
878 | + frm_cfg.frame_pin_dir = regk_sser_out; | |
879 | + frm_cfg.out_on = regk_sser_intern_tb; | |
880 | + gen_cfg.clk_dir = regk_sser_out; | |
881 | + break; | |
882 | + case SLAVE_INPUT: | |
883 | + port->output = 0; | |
884 | + port->input = 1; | |
885 | + frm_cfg.frame_pin_dir = regk_sser_in; | |
886 | + gen_cfg.clk_dir = regk_sser_in; | |
887 | + break; | |
888 | + case MASTER_BIDIR: | |
889 | + port->output = 1; | |
890 | + port->input = 1; | |
891 | + frm_cfg.frame_pin_dir = regk_sser_out; | |
892 | + frm_cfg.out_on = regk_sser_intern_tb; | |
893 | + gen_cfg.clk_dir = regk_sser_out; | |
894 | + break; | |
895 | + case SLAVE_BIDIR: | |
896 | + port->output = 1; | |
897 | + port->input = 1; | |
898 | + frm_cfg.frame_pin_dir = regk_sser_in; | |
899 | + gen_cfg.clk_dir = regk_sser_in; | |
900 | + break; | |
901 | + default: | |
902 | + spin_unlock_irq(&port->lock); | |
903 | + return -EINVAL; | |
814 | 904 | } |
815 | - if (!port->use_dma || (arg == MASTER_OUTPUT || arg == SLAVE_OUTPUT)) | |
905 | + if (!port->use_dma || arg == MASTER_OUTPUT || | |
906 | + arg == SLAVE_OUTPUT) | |
816 | 907 | intr_mask.rdav = regk_sser_yes; |
817 | 908 | break; |
818 | 909 | case SSP_FRAME_SYNC: |
819 | 910 | if (arg & NORMAL_SYNC) { |
820 | 911 | frm_cfg.rec_delay = 1; |
821 | 912 | frm_cfg.tr_delay = 1; |
822 | - } | |
823 | - else if (arg & EARLY_SYNC) | |
913 | + } else if (arg & EARLY_SYNC) | |
824 | 914 | frm_cfg.rec_delay = frm_cfg.tr_delay = 0; |
825 | - else if (arg & SECOND_WORD_SYNC) { | |
915 | + else if (arg & LATE_SYNC) { | |
916 | + frm_cfg.tr_delay = 2; | |
917 | + frm_cfg.rec_delay = 2; | |
918 | + } else if (arg & SECOND_WORD_SYNC) { | |
826 | 919 | frm_cfg.rec_delay = 7; |
827 | 920 | frm_cfg.tr_delay = 1; |
828 | 921 | } |
829 | 922 | |
... | ... | @@ -914,15 +1007,12 @@ |
914 | 1007 | frm_cfg.type = regk_sser_level; |
915 | 1008 | frm_cfg.tr_delay = 1; |
916 | 1009 | frm_cfg.level = regk_sser_neg_lo; |
917 | - if (arg & SPI_SLAVE) | |
918 | - { | |
1010 | + if (arg & SPI_SLAVE) { | |
919 | 1011 | rec_cfg.clk_pol = regk_sser_neg; |
920 | 1012 | gen_cfg.clk_dir = regk_sser_in; |
921 | 1013 | port->input = 1; |
922 | 1014 | port->output = 0; |
923 | - } | |
924 | - else | |
925 | - { | |
1015 | + } else { | |
926 | 1016 | gen_cfg.out_clk_pol = regk_sser_pos; |
927 | 1017 | port->input = 0; |
928 | 1018 | port->output = 1; |
929 | 1019 | |
930 | 1020 | |
931 | 1021 | |
932 | 1022 | |
... | ... | @@ -965,19 +1055,19 @@ |
965 | 1055 | } |
966 | 1056 | |
967 | 1057 | static long sync_serial_ioctl(struct file *file, |
968 | - unsigned int cmd, unsigned long arg) | |
1058 | + unsigned int cmd, unsigned long arg) | |
969 | 1059 | { |
970 | - long ret; | |
1060 | + long ret; | |
971 | 1061 | |
972 | - mutex_lock(&sync_serial_mutex); | |
973 | - ret = sync_serial_ioctl_unlocked(file, cmd, arg); | |
974 | - mutex_unlock(&sync_serial_mutex); | |
1062 | + mutex_lock(&sync_serial_mutex); | |
1063 | + ret = sync_serial_ioctl_unlocked(file, cmd, arg); | |
1064 | + mutex_unlock(&sync_serial_mutex); | |
975 | 1065 | |
976 | - return ret; | |
1066 | + return ret; | |
977 | 1067 | } |
978 | 1068 | |
979 | 1069 | /* NOTE: sync_serial_write does not support concurrency */ |
980 | -static ssize_t sync_serial_write(struct file *file, const char *buf, | |
1070 | +static ssize_t sync_serial_write(struct file *file, const char __user *buf, | |
981 | 1071 | size_t count, loff_t *ppos) |
982 | 1072 | { |
983 | 1073 | int dev = iminor(file_inode(file)); |
... | ... | @@ -993,7 +1083,7 @@ |
993 | 1083 | unsigned char *buf_stop_ptr; /* Last byte + 1 */ |
994 | 1084 | |
995 | 1085 | if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) { |
996 | - DEBUG(printk("Invalid minor %d\n", dev)); | |
1086 | + DEBUG(pr_info("Invalid minor %d\n", dev)); | |
997 | 1087 | return -ENODEV; |
998 | 1088 | } |
999 | 1089 | port = &ports[dev]; |
... | ... | @@ -1006,9 +1096,9 @@ |
1006 | 1096 | * |_________|___________________|________________________| |
1007 | 1097 | * ^ rd_ptr ^ wr_ptr |
1008 | 1098 | */ |
1009 | - DEBUGWRITE(printk(KERN_DEBUG "W d%d c %lu a: %p c: %p\n", | |
1010 | - port->port_nbr, count, port->active_tr_descr, | |
1011 | - port->catch_tr_descr)); | |
1099 | + DEBUGWRITE(pr_info("W d%d c %u a: %p c: %p\n", | |
1100 | + port->port_nbr, count, port->active_tr_descr, | |
1101 | + port->catch_tr_descr)); | |
1012 | 1102 | |
1013 | 1103 | /* Read variables that may be updated by interrupts */ |
1014 | 1104 | spin_lock_irqsave(&port->lock, flags); |
... | ... | @@ -1020,7 +1110,7 @@ |
1020 | 1110 | if (port->tr_running && |
1021 | 1111 | ((port->use_dma && port->active_tr_descr == port->catch_tr_descr) || |
1022 | 1112 | out_buf_count >= OUT_BUFFER_SIZE)) { |
1023 | - DEBUGWRITE(printk(KERN_DEBUG "sser%d full\n", dev)); | |
1113 | + DEBUGWRITE(pr_info("sser%d full\n", dev)); | |
1024 | 1114 | return -EAGAIN; |
1025 | 1115 | } |
1026 | 1116 | |
1027 | 1117 | |
... | ... | @@ -1043,15 +1133,16 @@ |
1043 | 1133 | if (copy_from_user(wr_ptr, buf, trunc_count)) |
1044 | 1134 | return -EFAULT; |
1045 | 1135 | |
1046 | - DEBUGOUTBUF(printk(KERN_DEBUG "%-4d + %-4d = %-4d %p %p %p\n", | |
1047 | - out_buf_count, trunc_count, | |
1048 | - port->out_buf_count, port->out_buffer, | |
1049 | - wr_ptr, buf_stop_ptr)); | |
1136 | + DEBUGOUTBUF(pr_info("%-4d + %-4d = %-4d %p %p %p\n", | |
1137 | + out_buf_count, trunc_count, | |
1138 | + port->out_buf_count, port->out_buffer, | |
1139 | + wr_ptr, buf_stop_ptr)); | |
1050 | 1140 | |
1051 | 1141 | /* Make sure transmitter/receiver is running */ |
1052 | 1142 | if (!port->started) { |
1053 | 1143 | reg_sser_rw_cfg cfg = REG_RD(sser, port->regi_sser, rw_cfg); |
1054 | - reg_sser_rw_rec_cfg rec_cfg = REG_RD(sser, port->regi_sser, rw_rec_cfg); | |
1144 | + reg_sser_rw_rec_cfg rec_cfg = | |
1145 | + REG_RD(sser, port->regi_sser, rw_rec_cfg); | |
1055 | 1146 | cfg.en = regk_sser_yes; |
1056 | 1147 | rec_cfg.rec_en = port->input; |
1057 | 1148 | REG_WR(sser, port->regi_sser, rw_cfg, cfg); |
1058 | 1149 | |
1059 | 1150 | |
... | ... | @@ -1068,8 +1159,11 @@ |
1068 | 1159 | spin_lock_irqsave(&port->lock, flags); |
1069 | 1160 | port->out_buf_count += trunc_count; |
1070 | 1161 | if (port->use_dma) { |
1162 | +#ifdef SYNC_SER_DMA | |
1071 | 1163 | start_dma_out(port, wr_ptr, trunc_count); |
1164 | +#endif | |
1072 | 1165 | } else if (!port->tr_running) { |
1166 | +#ifdef SYNC_SER_MANUAL | |
1073 | 1167 | reg_sser_rw_intr_mask intr_mask; |
1074 | 1168 | intr_mask = REG_RD(sser, port->regi_sser, rw_intr_mask); |
1075 | 1169 | /* Start sender by writing data */ |
1076 | 1170 | |
... | ... | @@ -1077,14 +1171,15 @@ |
1077 | 1171 | /* and enable transmitter ready IRQ */ |
1078 | 1172 | intr_mask.trdy = 1; |
1079 | 1173 | REG_WR(sser, port->regi_sser, rw_intr_mask, intr_mask); |
1174 | +#endif | |
1080 | 1175 | } |
1081 | 1176 | spin_unlock_irqrestore(&port->lock, flags); |
1082 | 1177 | |
1083 | 1178 | /* Exit if non blocking */ |
1084 | 1179 | if (file->f_flags & O_NONBLOCK) { |
1085 | - DEBUGWRITE(printk(KERN_DEBUG "w d%d c %lu %08x\n", | |
1086 | - port->port_nbr, trunc_count, | |
1087 | - REG_RD_INT(dma, port->regi_dmaout, r_intr))); | |
1180 | + DEBUGWRITE(pr_info("w d%d c %u %08x\n", | |
1181 | + port->port_nbr, trunc_count, | |
1182 | + REG_RD_INT(dma, port->regi_dmaout, r_intr))); | |
1088 | 1183 | return trunc_count; |
1089 | 1184 | } |
1090 | 1185 | |
1091 | 1186 | |
1092 | 1187 | |
1093 | 1188 | |
1094 | 1189 | |
1095 | 1190 | |
... | ... | @@ -1094,105 +1189,32 @@ |
1094 | 1189 | if (signal_pending(current)) |
1095 | 1190 | return -EINTR; |
1096 | 1191 | |
1097 | - DEBUGWRITE(printk(KERN_DEBUG "w d%d c %lu\n", | |
1098 | - port->port_nbr, trunc_count)); | |
1192 | + DEBUGWRITE(pr_info("w d%d c %u\n", port->port_nbr, trunc_count)); | |
1099 | 1193 | return trunc_count; |
1100 | 1194 | } |
1101 | 1195 | |
1102 | -static ssize_t sync_serial_read(struct file * file, char * buf, | |
1196 | +static ssize_t sync_serial_read(struct file *file, char __user *buf, | |
1103 | 1197 | size_t count, loff_t *ppos) |
1104 | 1198 | { |
1105 | - int dev = iminor(file_inode(file)); | |
1106 | - int avail; | |
1107 | - sync_port *port; | |
1108 | - unsigned char* start; | |
1109 | - unsigned char* end; | |
1110 | - unsigned long flags; | |
1111 | - | |
1112 | - if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) | |
1113 | - { | |
1114 | - DEBUG(printk("Invalid minor %d\n", dev)); | |
1115 | - return -ENODEV; | |
1116 | - } | |
1117 | - port = &ports[dev]; | |
1118 | - | |
1119 | - DEBUGREAD(printk("R%d c %d ri %lu wi %lu /%lu\n", dev, count, port->readp - port->flip, port->writep - port->flip, port->in_buffer_size)); | |
1120 | - | |
1121 | - if (!port->started) | |
1122 | - { | |
1123 | - reg_sser_rw_cfg cfg = REG_RD(sser, port->regi_sser, rw_cfg); | |
1124 | - reg_sser_rw_tr_cfg tr_cfg = REG_RD(sser, port->regi_sser, rw_tr_cfg); | |
1125 | - reg_sser_rw_rec_cfg rec_cfg = REG_RD(sser, port->regi_sser, rw_rec_cfg); | |
1126 | - cfg.en = regk_sser_yes; | |
1127 | - tr_cfg.tr_en = regk_sser_yes; | |
1128 | - rec_cfg.rec_en = regk_sser_yes; | |
1129 | - REG_WR(sser, port->regi_sser, rw_cfg, cfg); | |
1130 | - REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg); | |
1131 | - REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg); | |
1132 | - port->started = 1; | |
1133 | - } | |
1134 | - | |
1135 | - /* Calculate number of available bytes */ | |
1136 | - /* Save pointers to avoid that they are modified by interrupt */ | |
1137 | - spin_lock_irqsave(&port->lock, flags); | |
1138 | - start = (unsigned char*)port->readp; /* cast away volatile */ | |
1139 | - end = (unsigned char*)port->writep; /* cast away volatile */ | |
1140 | - spin_unlock_irqrestore(&port->lock, flags); | |
1141 | - while ((start == end) && !port->full) /* No data */ | |
1142 | - { | |
1143 | - DEBUGREAD(printk(KERN_DEBUG "&")); | |
1144 | - if (file->f_flags & O_NONBLOCK) | |
1145 | - return -EAGAIN; | |
1146 | - | |
1147 | - wait_event_interruptible(port->in_wait_q, | |
1148 | - !(start == end && !port->full)); | |
1149 | - if (signal_pending(current)) | |
1150 | - return -EINTR; | |
1151 | - | |
1152 | - spin_lock_irqsave(&port->lock, flags); | |
1153 | - start = (unsigned char*)port->readp; /* cast away volatile */ | |
1154 | - end = (unsigned char*)port->writep; /* cast away volatile */ | |
1155 | - spin_unlock_irqrestore(&port->lock, flags); | |
1156 | - } | |
1157 | - | |
1158 | - /* Lazy read, never return wrapped data. */ | |
1159 | - if (port->full) | |
1160 | - avail = port->in_buffer_size; | |
1161 | - else if (end > start) | |
1162 | - avail = end - start; | |
1163 | - else | |
1164 | - avail = port->flip + port->in_buffer_size - start; | |
1165 | - | |
1166 | - count = count > avail ? avail : count; | |
1167 | - if (copy_to_user(buf, start, count)) | |
1168 | - return -EFAULT; | |
1169 | - /* Disable interrupts while updating readp */ | |
1170 | - spin_lock_irqsave(&port->lock, flags); | |
1171 | - port->readp += count; | |
1172 | - if (port->readp >= port->flip + port->in_buffer_size) /* Wrap? */ | |
1173 | - port->readp = port->flip; | |
1174 | - port->full = 0; | |
1175 | - spin_unlock_irqrestore(&port->lock, flags); | |
1176 | - DEBUGREAD(printk("r %d\n", count)); | |
1177 | - return count; | |
1199 | + return __sync_serial_read(file, buf, count, ppos, NULL); | |
1178 | 1200 | } |
1179 | 1201 | |
1180 | -static void send_word(sync_port* port) | |
1202 | +#ifdef SYNC_SER_MANUAL | |
1203 | +static void send_word(struct sync_port *port) | |
1181 | 1204 | { |
1182 | 1205 | reg_sser_rw_tr_cfg tr_cfg = REG_RD(sser, port->regi_sser, rw_tr_cfg); |
1183 | 1206 | reg_sser_rw_tr_data tr_data = {0}; |
1184 | 1207 | |
1185 | - switch(tr_cfg.sample_size) | |
1208 | + switch (tr_cfg.sample_size) { | |
1209 | + case 8: | |
1210 | + port->out_buf_count--; | |
1211 | + tr_data.data = *port->out_rd_ptr++; | |
1212 | + REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); | |
1213 | + if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE) | |
1214 | + port->out_rd_ptr = port->out_buffer; | |
1215 | + break; | |
1216 | + case 12: | |
1186 | 1217 | { |
1187 | - case 8: | |
1188 | - port->out_buf_count--; | |
1189 | - tr_data.data = *port->out_rd_ptr++; | |
1190 | - REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); | |
1191 | - if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE) | |
1192 | - port->out_rd_ptr = port->out_buffer; | |
1193 | - break; | |
1194 | - case 12: | |
1195 | - { | |
1196 | 1218 | int data = (*port->out_rd_ptr++) << 8; |
1197 | 1219 | data |= *port->out_rd_ptr++; |
1198 | 1220 | port->out_buf_count -= 2; |
1199 | 1221 | |
... | ... | @@ -1200,8 +1222,8 @@ |
1200 | 1222 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); |
1201 | 1223 | if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE) |
1202 | 1224 | port->out_rd_ptr = port->out_buffer; |
1225 | + break; | |
1203 | 1226 | } |
1204 | - break; | |
1205 | 1227 | case 16: |
1206 | 1228 | port->out_buf_count -= 2; |
1207 | 1229 | tr_data.data = *(unsigned short *)port->out_rd_ptr; |
1208 | 1230 | |
1209 | 1231 | |
1210 | 1232 | |
1211 | 1233 | |
1212 | 1234 | |
... | ... | @@ -1233,27 +1255,28 @@ |
1233 | 1255 | break; |
1234 | 1256 | } |
1235 | 1257 | } |
1258 | +#endif | |
1236 | 1259 | |
1237 | -static void start_dma_out(struct sync_port *port, | |
1238 | - const char *data, int count) | |
1260 | +#ifdef SYNC_SER_DMA | |
1261 | +static void start_dma_out(struct sync_port *port, const char *data, int count) | |
1239 | 1262 | { |
1240 | - port->active_tr_descr->buf = (char *) virt_to_phys((char *) data); | |
1263 | + port->active_tr_descr->buf = (char *)virt_to_phys((char *)data); | |
1241 | 1264 | port->active_tr_descr->after = port->active_tr_descr->buf + count; |
1242 | 1265 | port->active_tr_descr->intr = 1; |
1243 | 1266 | |
1244 | 1267 | port->active_tr_descr->eol = 1; |
1245 | 1268 | port->prev_tr_descr->eol = 0; |
1246 | 1269 | |
1247 | - DEBUGTRDMA(printk(KERN_DEBUG "Inserting eolr:%p eol@:%p\n", | |
1270 | + DEBUGTRDMA(pr_info("Inserting eolr:%p eol@:%p\n", | |
1248 | 1271 | port->prev_tr_descr, port->active_tr_descr)); |
1249 | 1272 | port->prev_tr_descr = port->active_tr_descr; |
1250 | - port->active_tr_descr = phys_to_virt((int) port->active_tr_descr->next); | |
1273 | + port->active_tr_descr = phys_to_virt((int)port->active_tr_descr->next); | |
1251 | 1274 | |
1252 | 1275 | if (!port->tr_running) { |
1253 | 1276 | reg_sser_rw_tr_cfg tr_cfg = REG_RD(sser, port->regi_sser, |
1254 | 1277 | rw_tr_cfg); |
1255 | 1278 | |
1256 | - port->out_context.next = 0; | |
1279 | + port->out_context.next = NULL; | |
1257 | 1280 | port->out_context.saved_data = |
1258 | 1281 | (dma_descr_data *)virt_to_phys(port->prev_tr_descr); |
1259 | 1282 | port->out_context.saved_data_buf = port->prev_tr_descr->buf; |
1260 | 1283 | |
1261 | 1284 | |
1262 | 1285 | |
1263 | 1286 | |
1264 | 1287 | |
1265 | 1288 | |
1266 | 1289 | |
1267 | 1290 | |
1268 | 1291 | |
1269 | 1292 | |
1270 | 1293 | |
... | ... | @@ -1263,57 +1286,58 @@ |
1263 | 1286 | |
1264 | 1287 | tr_cfg.tr_en = regk_sser_yes; |
1265 | 1288 | REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg); |
1266 | - DEBUGTRDMA(printk(KERN_DEBUG "dma s\n");); | |
1289 | + DEBUGTRDMA(pr_info(KERN_INFO "dma s\n");); | |
1267 | 1290 | } else { |
1268 | 1291 | DMA_CONTINUE_DATA(port->regi_dmaout); |
1269 | - DEBUGTRDMA(printk(KERN_DEBUG "dma c\n");); | |
1292 | + DEBUGTRDMA(pr_info("dma c\n");); | |
1270 | 1293 | } |
1271 | 1294 | |
1272 | 1295 | port->tr_running = 1; |
1273 | 1296 | } |
1274 | 1297 | |
1275 | -static void start_dma_in(sync_port *port) | |
1298 | +static void start_dma_in(struct sync_port *port) | |
1276 | 1299 | { |
1277 | 1300 | int i; |
1278 | 1301 | char *buf; |
1302 | + unsigned long flags; | |
1303 | + spin_lock_irqsave(&port->lock, flags); | |
1279 | 1304 | port->writep = port->flip; |
1305 | + spin_unlock_irqrestore(&port->lock, flags); | |
1280 | 1306 | |
1281 | - if (port->writep > port->flip + port->in_buffer_size) { | |
1282 | - panic("Offset too large in sync serial driver\n"); | |
1283 | - return; | |
1284 | - } | |
1285 | - buf = (char*)virt_to_phys(port->in_buffer); | |
1307 | + buf = (char *)virt_to_phys(port->in_buffer); | |
1286 | 1308 | for (i = 0; i < NBR_IN_DESCR; i++) { |
1287 | 1309 | port->in_descr[i].buf = buf; |
1288 | 1310 | port->in_descr[i].after = buf + port->inbufchunk; |
1289 | 1311 | port->in_descr[i].intr = 1; |
1290 | - port->in_descr[i].next = (dma_descr_data*)virt_to_phys(&port->in_descr[i+1]); | |
1312 | + port->in_descr[i].next = | |
1313 | + (dma_descr_data *)virt_to_phys(&port->in_descr[i+1]); | |
1291 | 1314 | port->in_descr[i].buf = buf; |
1292 | 1315 | buf += port->inbufchunk; |
1293 | 1316 | } |
1294 | 1317 | /* Link the last descriptor to the first */ |
1295 | - port->in_descr[i-1].next = (dma_descr_data*)virt_to_phys(&port->in_descr[0]); | |
1318 | + port->in_descr[i-1].next = | |
1319 | + (dma_descr_data *)virt_to_phys(&port->in_descr[0]); | |
1296 | 1320 | port->in_descr[i-1].eol = regk_sser_yes; |
1297 | 1321 | port->next_rx_desc = &port->in_descr[0]; |
1298 | 1322 | port->prev_rx_desc = &port->in_descr[NBR_IN_DESCR - 1]; |
1299 | - port->in_context.saved_data = (dma_descr_data*)virt_to_phys(&port->in_descr[0]); | |
1323 | + port->in_context.saved_data = | |
1324 | + (dma_descr_data *)virt_to_phys(&port->in_descr[0]); | |
1300 | 1325 | port->in_context.saved_data_buf = port->in_descr[0].buf; |
1301 | 1326 | DMA_START_CONTEXT(port->regi_dmain, virt_to_phys(&port->in_context)); |
1302 | 1327 | } |
1303 | 1328 | |
1304 | -#ifdef SYNC_SER_DMA | |
1305 | 1329 | static irqreturn_t tr_interrupt(int irq, void *dev_id) |
1306 | 1330 | { |
1307 | 1331 | reg_dma_r_masked_intr masked; |
1308 | - reg_dma_rw_ack_intr ack_intr = {.data = regk_dma_yes}; | |
1332 | + reg_dma_rw_ack_intr ack_intr = { .data = regk_dma_yes }; | |
1309 | 1333 | reg_dma_rw_stat stat; |
1310 | 1334 | int i; |
1311 | 1335 | int found = 0; |
1312 | 1336 | int stop_sser = 0; |
1313 | 1337 | |
1314 | 1338 | for (i = 0; i < NBR_PORTS; i++) { |
1315 | - sync_port *port = &ports[i]; | |
1316 | - if (!port->enabled || !port->use_dma) | |
1339 | + struct sync_port *port = &ports[i]; | |
1340 | + if (!port->enabled || !port->use_dma) | |
1317 | 1341 | continue; |
1318 | 1342 | |
1319 | 1343 | /* IRQ active for the port? */ |
1320 | 1344 | |
... | ... | @@ -1338,19 +1362,20 @@ |
1338 | 1362 | int sent; |
1339 | 1363 | sent = port->catch_tr_descr->after - |
1340 | 1364 | port->catch_tr_descr->buf; |
1341 | - DEBUGTXINT(printk(KERN_DEBUG "%-4d - %-4d = %-4d\t" | |
1342 | - "in descr %p (ac: %p)\n", | |
1343 | - port->out_buf_count, sent, | |
1344 | - port->out_buf_count - sent, | |
1345 | - port->catch_tr_descr, | |
1346 | - port->active_tr_descr);); | |
1365 | + DEBUGTXINT(pr_info("%-4d - %-4d = %-4d\t" | |
1366 | + "in descr %p (ac: %p)\n", | |
1367 | + port->out_buf_count, sent, | |
1368 | + port->out_buf_count - sent, | |
1369 | + port->catch_tr_descr, | |
1370 | + port->active_tr_descr);); | |
1347 | 1371 | port->out_buf_count -= sent; |
1348 | 1372 | port->catch_tr_descr = |
1349 | 1373 | phys_to_virt((int) port->catch_tr_descr->next); |
1350 | 1374 | port->out_rd_ptr = |
1351 | 1375 | phys_to_virt((int) port->catch_tr_descr->buf); |
1352 | 1376 | } else { |
1353 | - int i, sent; | |
1377 | + reg_sser_rw_tr_cfg tr_cfg; | |
1378 | + int j, sent; | |
1354 | 1379 | /* EOL handler. |
1355 | 1380 | * Note that if an EOL was encountered during the irq |
1356 | 1381 | * locked section of sync_ser_write the DMA will be |
1357 | 1382 | |
... | ... | @@ -1358,11 +1383,11 @@ |
1358 | 1383 | * The remaining descriptors will be traversed by |
1359 | 1384 | * the descriptor interrupts as usual. |
1360 | 1385 | */ |
1361 | - i = 0; | |
1386 | + j = 0; | |
1362 | 1387 | while (!port->catch_tr_descr->eol) { |
1363 | 1388 | sent = port->catch_tr_descr->after - |
1364 | 1389 | port->catch_tr_descr->buf; |
1365 | - DEBUGOUTBUF(printk(KERN_DEBUG | |
1390 | + DEBUGOUTBUF(pr_info( | |
1366 | 1391 | "traversing descr %p -%d (%d)\n", |
1367 | 1392 | port->catch_tr_descr, |
1368 | 1393 | sent, |
1369 | 1394 | |
... | ... | @@ -1370,16 +1395,15 @@ |
1370 | 1395 | port->out_buf_count -= sent; |
1371 | 1396 | port->catch_tr_descr = phys_to_virt( |
1372 | 1397 | (int)port->catch_tr_descr->next); |
1373 | - i++; | |
1374 | - if (i >= NBR_OUT_DESCR) { | |
1398 | + j++; | |
1399 | + if (j >= NBR_OUT_DESCR) { | |
1375 | 1400 | /* TODO: Reset and recover */ |
1376 | 1401 | panic("sync_serial: missing eol"); |
1377 | 1402 | } |
1378 | 1403 | } |
1379 | 1404 | sent = port->catch_tr_descr->after - |
1380 | 1405 | port->catch_tr_descr->buf; |
1381 | - DEBUGOUTBUF(printk(KERN_DEBUG | |
1382 | - "eol at descr %p -%d (%d)\n", | |
1406 | + DEBUGOUTBUF(pr_info("eol at descr %p -%d (%d)\n", | |
1383 | 1407 | port->catch_tr_descr, |
1384 | 1408 | sent, |
1385 | 1409 | port->out_buf_count)); |
1386 | 1410 | |
... | ... | @@ -1394,15 +1418,13 @@ |
1394 | 1418 | OUT_BUFFER_SIZE) |
1395 | 1419 | port->out_rd_ptr = port->out_buffer; |
1396 | 1420 | |
1397 | - reg_sser_rw_tr_cfg tr_cfg = | |
1398 | - REG_RD(sser, port->regi_sser, rw_tr_cfg); | |
1399 | - DEBUGTXINT(printk(KERN_DEBUG | |
1421 | + tr_cfg = REG_RD(sser, port->regi_sser, rw_tr_cfg); | |
1422 | + DEBUGTXINT(pr_info( | |
1400 | 1423 | "tr_int DMA stop %d, set catch @ %p\n", |
1401 | 1424 | port->out_buf_count, |
1402 | 1425 | port->active_tr_descr)); |
1403 | 1426 | if (port->out_buf_count != 0) |
1404 | - printk(KERN_CRIT "sync_ser: buffer not " | |
1405 | - "empty after eol.\n"); | |
1427 | + pr_err("sync_ser: buf not empty after eol\n"); | |
1406 | 1428 | port->catch_tr_descr = port->active_tr_descr; |
1407 | 1429 | port->tr_running = 0; |
1408 | 1430 | tr_cfg.tr_en = regk_sser_no; |
1409 | 1431 | |
1410 | 1432 | |
1411 | 1433 | |
1412 | 1434 | |
1413 | 1435 | |
... | ... | @@ -1414,62 +1436,79 @@ |
1414 | 1436 | return IRQ_RETVAL(found); |
1415 | 1437 | } /* tr_interrupt */ |
1416 | 1438 | |
1439 | + | |
1440 | +static inline void handle_rx_packet(struct sync_port *port) | |
1441 | +{ | |
1442 | + int idx; | |
1443 | + reg_dma_rw_ack_intr ack_intr = { .data = regk_dma_yes }; | |
1444 | + unsigned long flags; | |
1445 | + | |
1446 | + DEBUGRXINT(pr_info(KERN_INFO "!")); | |
1447 | + spin_lock_irqsave(&port->lock, flags); | |
1448 | + | |
1449 | + /* If we overrun the user experience is crap regardless if we | |
1450 | + * drop new or old data. Its much easier to get it right when | |
1451 | + * dropping new data so lets do that. | |
1452 | + */ | |
1453 | + if ((port->writep + port->inbufchunk <= | |
1454 | + port->flip + port->in_buffer_size) && | |
1455 | + (port->in_buffer_len + port->inbufchunk < IN_BUFFER_SIZE)) { | |
1456 | + memcpy(port->writep, | |
1457 | + phys_to_virt((unsigned)port->next_rx_desc->buf), | |
1458 | + port->inbufchunk); | |
1459 | + port->writep += port->inbufchunk; | |
1460 | + if (port->writep >= port->flip + port->in_buffer_size) | |
1461 | + port->writep = port->flip; | |
1462 | + | |
1463 | + /* Timestamp the new data chunk. */ | |
1464 | + if (port->write_ts_idx == NBR_IN_DESCR) | |
1465 | + port->write_ts_idx = 0; | |
1466 | + idx = port->write_ts_idx++; | |
1467 | + do_posix_clock_monotonic_gettime(&port->timestamp[idx]); | |
1468 | + port->in_buffer_len += port->inbufchunk; | |
1469 | + } | |
1470 | + spin_unlock_irqrestore(&port->lock, flags); | |
1471 | + | |
1472 | + port->next_rx_desc->eol = 1; | |
1473 | + port->prev_rx_desc->eol = 0; | |
1474 | + /* Cache bug workaround */ | |
1475 | + flush_dma_descr(port->prev_rx_desc, 0); | |
1476 | + port->prev_rx_desc = port->next_rx_desc; | |
1477 | + port->next_rx_desc = phys_to_virt((unsigned)port->next_rx_desc->next); | |
1478 | + /* Cache bug workaround */ | |
1479 | + flush_dma_descr(port->prev_rx_desc, 1); | |
1480 | + /* wake up the waiting process */ | |
1481 | + wake_up_interruptible(&port->in_wait_q); | |
1482 | + DMA_CONTINUE(port->regi_dmain); | |
1483 | + REG_WR(dma, port->regi_dmain, rw_ack_intr, ack_intr); | |
1484 | + | |
1485 | +} | |
1486 | + | |
1417 | 1487 | static irqreturn_t rx_interrupt(int irq, void *dev_id) |
1418 | 1488 | { |
1419 | 1489 | reg_dma_r_masked_intr masked; |
1420 | - reg_dma_rw_ack_intr ack_intr = {.data = regk_dma_yes}; | |
1421 | 1490 | |
1422 | 1491 | int i; |
1423 | 1492 | int found = 0; |
1424 | 1493 | |
1425 | - for (i = 0; i < NBR_PORTS; i++) | |
1426 | - { | |
1427 | - sync_port *port = &ports[i]; | |
1494 | + DEBUG(pr_info("rx_interrupt\n")); | |
1428 | 1495 | |
1429 | - if (!port->enabled || !port->use_dma ) | |
1496 | + for (i = 0; i < NBR_PORTS; i++) { | |
1497 | + struct sync_port *port = &ports[i]; | |
1498 | + | |
1499 | + if (!port->enabled || !port->use_dma) | |
1430 | 1500 | continue; |
1431 | 1501 | |
1432 | 1502 | masked = REG_RD(dma, port->regi_dmain, r_masked_intr); |
1433 | 1503 | |
1434 | - if (masked.data) /* Descriptor interrupt */ | |
1435 | - { | |
1436 | - found = 1; | |
1437 | - while (REG_RD(dma, port->regi_dmain, rw_data) != | |
1438 | - virt_to_phys(port->next_rx_desc)) { | |
1439 | - DEBUGRXINT(printk(KERN_DEBUG "!")); | |
1440 | - if (port->writep + port->inbufchunk > port->flip + port->in_buffer_size) { | |
1441 | - int first_size = port->flip + port->in_buffer_size - port->writep; | |
1442 | - memcpy((char*)port->writep, phys_to_virt((unsigned)port->next_rx_desc->buf), first_size); | |
1443 | - memcpy(port->flip, phys_to_virt((unsigned)port->next_rx_desc->buf+first_size), port->inbufchunk - first_size); | |
1444 | - port->writep = port->flip + port->inbufchunk - first_size; | |
1445 | - } else { | |
1446 | - memcpy((char*)port->writep, | |
1447 | - phys_to_virt((unsigned)port->next_rx_desc->buf), | |
1448 | - port->inbufchunk); | |
1449 | - port->writep += port->inbufchunk; | |
1450 | - if (port->writep >= port->flip + port->in_buffer_size) | |
1451 | - port->writep = port->flip; | |
1452 | - } | |
1453 | - if (port->writep == port->readp) | |
1454 | - { | |
1455 | - port->full = 1; | |
1456 | - } | |
1504 | + if (!masked.data) | |
1505 | + continue; | |
1457 | 1506 | |
1458 | - port->next_rx_desc->eol = 1; | |
1459 | - port->prev_rx_desc->eol = 0; | |
1460 | - /* Cache bug workaround */ | |
1461 | - flush_dma_descr(port->prev_rx_desc, 0); | |
1462 | - port->prev_rx_desc = port->next_rx_desc; | |
1463 | - port->next_rx_desc = phys_to_virt((unsigned)port->next_rx_desc->next); | |
1464 | - /* Cache bug workaround */ | |
1465 | - flush_dma_descr(port->prev_rx_desc, 1); | |
1466 | - /* wake up the waiting process */ | |
1467 | - wake_up_interruptible(&port->in_wait_q); | |
1468 | - DMA_CONTINUE(port->regi_dmain); | |
1469 | - REG_WR(dma, port->regi_dmain, rw_ack_intr, ack_intr); | |
1470 | - | |
1471 | - } | |
1472 | - } | |
1507 | + /* Descriptor interrupt */ | |
1508 | + found = 1; | |
1509 | + while (REG_RD(dma, port->regi_dmain, rw_data) != | |
1510 | + virt_to_phys(port->next_rx_desc)) | |
1511 | + handle_rx_packet(port); | |
1473 | 1512 | } |
1474 | 1513 | return IRQ_RETVAL(found); |
1475 | 1514 | } /* rx_interrupt */ |
1476 | 1515 | |
1477 | 1516 | |
1478 | 1517 | |
1479 | 1518 | |
1480 | 1519 | |
1481 | 1520 | |
1482 | 1521 | |
1483 | 1522 | |
1484 | 1523 | |
1485 | 1524 | |
1486 | 1525 | |
1487 | 1526 | |
1488 | 1527 | |
1489 | 1528 | |
1490 | 1529 | |
1491 | 1530 | |
1492 | 1531 | |
1493 | 1532 | |
1494 | 1533 | |
... | ... | @@ -1478,75 +1517,83 @@ |
1478 | 1517 | #ifdef SYNC_SER_MANUAL |
1479 | 1518 | static irqreturn_t manual_interrupt(int irq, void *dev_id) |
1480 | 1519 | { |
1520 | + unsigned long flags; | |
1481 | 1521 | int i; |
1482 | 1522 | int found = 0; |
1483 | 1523 | reg_sser_r_masked_intr masked; |
1484 | 1524 | |
1485 | - for (i = 0; i < NBR_PORTS; i++) | |
1486 | - { | |
1487 | - sync_port *port = &ports[i]; | |
1525 | + for (i = 0; i < NBR_PORTS; i++) { | |
1526 | + struct sync_port *port = &ports[i]; | |
1488 | 1527 | |
1489 | 1528 | if (!port->enabled || port->use_dma) |
1490 | - { | |
1491 | 1529 | continue; |
1492 | - } | |
1493 | 1530 | |
1494 | 1531 | masked = REG_RD(sser, port->regi_sser, r_masked_intr); |
1495 | - if (masked.rdav) /* Data received? */ | |
1496 | - { | |
1497 | - reg_sser_rw_rec_cfg rec_cfg = REG_RD(sser, port->regi_sser, rw_rec_cfg); | |
1498 | - reg_sser_r_rec_data data = REG_RD(sser, port->regi_sser, r_rec_data); | |
1532 | + /* Data received? */ | |
1533 | + if (masked.rdav) { | |
1534 | + reg_sser_rw_rec_cfg rec_cfg = | |
1535 | + REG_RD(sser, port->regi_sser, rw_rec_cfg); | |
1536 | + reg_sser_r_rec_data data = REG_RD(sser, | |
1537 | + port->regi_sser, r_rec_data); | |
1499 | 1538 | found = 1; |
1500 | 1539 | /* Read data */ |
1501 | - switch(rec_cfg.sample_size) | |
1502 | - { | |
1540 | + spin_lock_irqsave(&port->lock, flags); | |
1541 | + switch (rec_cfg.sample_size) { | |
1503 | 1542 | case 8: |
1504 | 1543 | *port->writep++ = data.data & 0xff; |
1505 | 1544 | break; |
1506 | 1545 | case 12: |
1507 | 1546 | *port->writep = (data.data & 0x0ff0) >> 4; |
1508 | 1547 | *(port->writep + 1) = data.data & 0x0f; |
1509 | - port->writep+=2; | |
1548 | + port->writep += 2; | |
1510 | 1549 | break; |
1511 | 1550 | case 16: |
1512 | - *(unsigned short*)port->writep = data.data; | |
1513 | - port->writep+=2; | |
1551 | + *(unsigned short *)port->writep = data.data; | |
1552 | + port->writep += 2; | |
1514 | 1553 | break; |
1515 | 1554 | case 24: |
1516 | - *(unsigned int*)port->writep = data.data; | |
1517 | - port->writep+=3; | |
1555 | + *(unsigned int *)port->writep = data.data; | |
1556 | + port->writep += 3; | |
1518 | 1557 | break; |
1519 | 1558 | case 32: |
1520 | - *(unsigned int*)port->writep = data.data; | |
1521 | - port->writep+=4; | |
1559 | + *(unsigned int *)port->writep = data.data; | |
1560 | + port->writep += 4; | |
1522 | 1561 | break; |
1523 | 1562 | } |
1524 | 1563 | |
1525 | - if (port->writep >= port->flip + port->in_buffer_size) /* Wrap? */ | |
1564 | + /* Wrap? */ | |
1565 | + if (port->writep >= port->flip + port->in_buffer_size) | |
1526 | 1566 | port->writep = port->flip; |
1527 | 1567 | if (port->writep == port->readp) { |
1528 | - /* receive buffer overrun, discard oldest data | |
1529 | - */ | |
1568 | + /* Receive buf overrun, discard oldest data */ | |
1530 | 1569 | port->readp++; |
1531 | - if (port->readp >= port->flip + port->in_buffer_size) /* Wrap? */ | |
1570 | + /* Wrap? */ | |
1571 | + if (port->readp >= port->flip + | |
1572 | + port->in_buffer_size) | |
1532 | 1573 | port->readp = port->flip; |
1533 | 1574 | } |
1575 | + spin_unlock_irqrestore(&port->lock, flags); | |
1534 | 1576 | if (sync_data_avail(port) >= port->inbufchunk) |
1535 | - wake_up_interruptible(&port->in_wait_q); /* Wake up application */ | |
1577 | + /* Wake up application */ | |
1578 | + wake_up_interruptible(&port->in_wait_q); | |
1536 | 1579 | } |
1537 | 1580 | |
1538 | - if (masked.trdy) /* Transmitter ready? */ | |
1539 | - { | |
1581 | + /* Transmitter ready? */ | |
1582 | + if (masked.trdy) { | |
1540 | 1583 | found = 1; |
1541 | - if (port->out_buf_count > 0) /* More data to send */ | |
1584 | + /* More data to send */ | |
1585 | + if (port->out_buf_count > 0) | |
1542 | 1586 | send_word(port); |
1543 | - else /* transmission finished */ | |
1544 | - { | |
1587 | + else { | |
1588 | + /* Transmission finished */ | |
1545 | 1589 | reg_sser_rw_intr_mask intr_mask; |
1546 | - intr_mask = REG_RD(sser, port->regi_sser, rw_intr_mask); | |
1590 | + intr_mask = REG_RD(sser, port->regi_sser, | |
1591 | + rw_intr_mask); | |
1547 | 1592 | intr_mask.trdy = 0; |
1548 | - REG_WR(sser, port->regi_sser, rw_intr_mask, intr_mask); | |
1549 | - wake_up_interruptible(&port->out_wait_q); /* Wake up application */ | |
1593 | + REG_WR(sser, port->regi_sser, | |
1594 | + rw_intr_mask, intr_mask); | |
1595 | + /* Wake up application */ | |
1596 | + wake_up_interruptible(&port->out_wait_q); | |
1550 | 1597 | } |
1551 | 1598 | } |
1552 | 1599 | } |
1553 | 1600 | |
... | ... | @@ -1554,5 +1601,109 @@ |
1554 | 1601 | } |
1555 | 1602 | #endif |
1556 | 1603 | |
1604 | +static int __init etrax_sync_serial_init(void) | |
1605 | +{ | |
1606 | +#if 1 | |
1607 | + /* This code will be removed when we move to udev for all devices. */ | |
1608 | + syncser_first = MKDEV(SYNC_SERIAL_MAJOR, 0); | |
1609 | + if (register_chrdev_region(syncser_first, minor_count, SYNCSER_NAME)) { | |
1610 | + pr_err("Failed to register major %d\n", SYNC_SERIAL_MAJOR); | |
1611 | + return -1; | |
1612 | + } | |
1613 | +#else | |
1614 | + /* Allocate dynamic major number. */ | |
1615 | + if (alloc_chrdev_region(&syncser_first, 0, minor_count, SYNCSER_NAME)) { | |
1616 | + pr_err("Failed to allocate character device region\n"); | |
1617 | + return -1; | |
1618 | + } | |
1619 | +#endif | |
1620 | + syncser_cdev = cdev_alloc(); | |
1621 | + if (!syncser_cdev) { | |
1622 | + pr_err("Failed to allocate cdev for syncser\n"); | |
1623 | + unregister_chrdev_region(syncser_first, minor_count); | |
1624 | + return -1; | |
1625 | + } | |
1626 | + cdev_init(syncser_cdev, &syncser_fops); | |
1627 | + | |
1628 | + /* Create a sysfs class for syncser */ | |
1629 | + syncser_class = class_create(THIS_MODULE, "syncser_class"); | |
1630 | + | |
1631 | + /* Initialize Ports */ | |
1632 | +#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) | |
1633 | + if (artpec_pinmux_alloc_fixed(PINMUX_SSER0)) { | |
1634 | + pr_warn("Unable to alloc pins for synchronous serial port 0\n"); | |
1635 | + unregister_chrdev_region(syncser_first, minor_count); | |
1636 | + return -EIO; | |
1637 | + } | |
1638 | + initialize_port(0); | |
1639 | + ports[0].enabled = 1; | |
1640 | + /* Register with sysfs so udev can pick it up. */ | |
1641 | + device_create(syncser_class, NULL, syncser_first, NULL, | |
1642 | + "%s%d", SYNCSER_NAME, 0); | |
1643 | +#endif | |
1644 | + | |
1645 | +#if defined(CONFIG_ETRAXFS) && defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) | |
1646 | + if (artpec_pinmux_alloc_fixed(PINMUX_SSER1)) { | |
1647 | + pr_warn("Unable to alloc pins for synchronous serial port 1\n"); | |
1648 | + unregister_chrdev_region(syncser_first, minor_count); | |
1649 | + class_destroy(syncser_class); | |
1650 | + return -EIO; | |
1651 | + } | |
1652 | + initialize_port(1); | |
1653 | + ports[1].enabled = 1; | |
1654 | + /* Register with sysfs so udev can pick it up. */ | |
1655 | + device_create(syncser_class, NULL, syncser_first, NULL, | |
1656 | + "%s%d", SYNCSER_NAME, 0); | |
1657 | +#endif | |
1658 | + | |
1659 | + /* Add it to system */ | |
1660 | + if (cdev_add(syncser_cdev, syncser_first, minor_count) < 0) { | |
1661 | + pr_err("Failed to add syncser as char device\n"); | |
1662 | + device_destroy(syncser_class, syncser_first); | |
1663 | + class_destroy(syncser_class); | |
1664 | + cdev_del(syncser_cdev); | |
1665 | + unregister_chrdev_region(syncser_first, minor_count); | |
1666 | + return -1; | |
1667 | + } | |
1668 | + | |
1669 | + | |
1670 | + pr_info("ARTPEC synchronous serial port (%s: %d, %d)\n", | |
1671 | + SYNCSER_NAME, MAJOR(syncser_first), MINOR(syncser_first)); | |
1672 | + | |
1673 | + return 0; | |
1674 | +} | |
1675 | + | |
1676 | +static void __exit etrax_sync_serial_exit(void) | |
1677 | +{ | |
1678 | + int i; | |
1679 | + device_destroy(syncser_class, syncser_first); | |
1680 | + class_destroy(syncser_class); | |
1681 | + | |
1682 | + if (syncser_cdev) { | |
1683 | + cdev_del(syncser_cdev); | |
1684 | + unregister_chrdev_region(syncser_first, minor_count); | |
1685 | + } | |
1686 | + for (i = 0; i < NBR_PORTS; i++) { | |
1687 | + struct sync_port *port = &ports[i]; | |
1688 | + if (port->init_irqs == dma_irq_setup) { | |
1689 | + /* Free dma irqs and dma channels. */ | |
1690 | +#ifdef SYNC_SER_DMA | |
1691 | + artpec_free_dma(port->dma_in_nbr); | |
1692 | + artpec_free_dma(port->dma_out_nbr); | |
1693 | + free_irq(port->dma_out_intr_vect, port); | |
1694 | + free_irq(port->dma_in_intr_vect, port); | |
1695 | +#endif | |
1696 | + } else if (port->init_irqs == manual_irq_setup) { | |
1697 | + /* Free manual irq. */ | |
1698 | + free_irq(port->syncser_intr_vect, port); | |
1699 | + } | |
1700 | + } | |
1701 | + | |
1702 | + pr_info("ARTPEC synchronous serial port unregistered\n"); | |
1703 | +} | |
1704 | + | |
1557 | 1705 | module_init(etrax_sync_serial_init); |
1706 | +module_exit(etrax_sync_serial_exit); | |
1707 | + | |
1708 | +MODULE_LICENSE("GPL"); |
arch/cris/arch-v32/kernel/debugport.c
... | ... | @@ -3,7 +3,9 @@ |
3 | 3 | */ |
4 | 4 | |
5 | 5 | #include <linux/console.h> |
6 | +#include <linux/kernel.h> | |
6 | 7 | #include <linux/init.h> |
8 | +#include <linux/string.h> | |
7 | 9 | #include <hwregs/reg_rdwr.h> |
8 | 10 | #include <hwregs/reg_map.h> |
9 | 11 | #include <hwregs/ser_defs.h> |
... | ... | @@ -65,6 +67,7 @@ |
65 | 67 | }, |
66 | 68 | #endif |
67 | 69 | }; |
70 | + | |
68 | 71 | static struct dbg_port *port = |
69 | 72 | #if defined(CONFIG_ETRAX_DEBUG_PORT0) |
70 | 73 | &ports[0]; |
71 | 74 | |
72 | 75 | |
73 | 76 | |
... | ... | @@ -97,14 +100,19 @@ |
97 | 100 | #endif |
98 | 101 | #endif |
99 | 102 | |
100 | -static void | |
101 | -start_port(struct dbg_port* p) | |
103 | +static void start_port(struct dbg_port *p) | |
102 | 104 | { |
103 | - if (!p) | |
104 | - return; | |
105 | + /* Set up serial port registers */ | |
106 | + reg_ser_rw_tr_ctrl tr_ctrl = {0}; | |
107 | + reg_ser_rw_tr_dma_en tr_dma_en = {0}; | |
105 | 108 | |
106 | - if (p->started) | |
109 | + reg_ser_rw_rec_ctrl rec_ctrl = {0}; | |
110 | + reg_ser_rw_tr_baud_div tr_baud_div = {0}; | |
111 | + reg_ser_rw_rec_baud_div rec_baud_div = {0}; | |
112 | + | |
113 | + if (!p || p->started) | |
107 | 114 | return; |
115 | + | |
108 | 116 | p->started = 1; |
109 | 117 | |
110 | 118 | if (p->nbr == 1) |
111 | 119 | |
112 | 120 | |
113 | 121 | |
... | ... | @@ -118,36 +126,24 @@ |
118 | 126 | crisv32_pinmux_alloc_fixed(pinmux_ser4); |
119 | 127 | #endif |
120 | 128 | |
121 | - /* Set up serial port registers */ | |
122 | - reg_ser_rw_tr_ctrl tr_ctrl = {0}; | |
123 | - reg_ser_rw_tr_dma_en tr_dma_en = {0}; | |
124 | - | |
125 | - reg_ser_rw_rec_ctrl rec_ctrl = {0}; | |
126 | - reg_ser_rw_tr_baud_div tr_baud_div = {0}; | |
127 | - reg_ser_rw_rec_baud_div rec_baud_div = {0}; | |
128 | - | |
129 | 129 | tr_ctrl.base_freq = rec_ctrl.base_freq = regk_ser_f29_493; |
130 | 130 | tr_dma_en.en = rec_ctrl.dma_mode = regk_ser_no; |
131 | 131 | tr_baud_div.div = rec_baud_div.div = 29493000 / p->baudrate / 8; |
132 | 132 | tr_ctrl.en = rec_ctrl.en = 1; |
133 | 133 | |
134 | - if (p->parity == 'O') | |
135 | - { | |
134 | + if (p->parity == 'O') { | |
136 | 135 | tr_ctrl.par_en = regk_ser_yes; |
137 | 136 | tr_ctrl.par = regk_ser_odd; |
138 | 137 | rec_ctrl.par_en = regk_ser_yes; |
139 | 138 | rec_ctrl.par = regk_ser_odd; |
140 | - } | |
141 | - else if (p->parity == 'E') | |
142 | - { | |
139 | + } else if (p->parity == 'E') { | |
143 | 140 | tr_ctrl.par_en = regk_ser_yes; |
144 | 141 | tr_ctrl.par = regk_ser_even; |
145 | 142 | rec_ctrl.par_en = regk_ser_yes; |
146 | 143 | rec_ctrl.par = regk_ser_odd; |
147 | 144 | } |
148 | 145 | |
149 | - if (p->bits == 7) | |
150 | - { | |
146 | + if (p->bits == 7) { | |
151 | 147 | tr_ctrl.data_bits = regk_ser_bits7; |
152 | 148 | rec_ctrl.data_bits = regk_ser_bits7; |
153 | 149 | } |
... | ... | @@ -161,8 +157,7 @@ |
161 | 157 | |
162 | 158 | #ifdef CONFIG_ETRAX_KGDB |
163 | 159 | /* Use polling to get a single character from the kernel debug port */ |
164 | -int | |
165 | -getDebugChar(void) | |
160 | +int getDebugChar(void) | |
166 | 161 | { |
167 | 162 | reg_ser_rs_stat_din stat; |
168 | 163 | reg_ser_rw_ack_intr ack_intr = { 0 }; |
... | ... | @@ -179,8 +174,7 @@ |
179 | 174 | } |
180 | 175 | |
181 | 176 | /* Use polling to put a single character to the kernel debug port */ |
182 | -void | |
183 | -putDebugChar(int val) | |
177 | +void putDebugChar(int val) | |
184 | 178 | { |
185 | 179 | reg_ser_r_stat_din stat; |
186 | 180 | do { |
187 | 181 | |
188 | 182 | |
... | ... | @@ -190,11 +184,47 @@ |
190 | 184 | } |
191 | 185 | #endif /* CONFIG_ETRAX_KGDB */ |
192 | 186 | |
187 | +static void __init early_putch(int c) | |
188 | +{ | |
189 | + reg_ser_r_stat_din stat; | |
190 | + /* Wait until transmitter is ready and send. */ | |
191 | + do | |
192 | + stat = REG_RD(ser, port->instance, r_stat_din); | |
193 | + while (!stat.tr_rdy); | |
194 | + REG_WR_INT(ser, port->instance, rw_dout, c); | |
195 | +} | |
196 | + | |
197 | +static void __init | |
198 | +early_console_write(struct console *con, const char *s, unsigned n) | |
199 | +{ | |
200 | + extern void reset_watchdog(void); | |
201 | + int i; | |
202 | + | |
203 | + /* Send data. */ | |
204 | + for (i = 0; i < n; i++) { | |
205 | + /* TODO: the '\n' -> '\n\r' translation should be done at the | |
206 | + receiver. Remove it when the serial driver removes it. */ | |
207 | + if (s[i] == '\n') | |
208 | + early_putch('\r'); | |
209 | + early_putch(s[i]); | |
210 | + reset_watchdog(); | |
211 | + } | |
212 | +} | |
213 | + | |
214 | +static struct console early_console_dev __initdata = { | |
215 | + .name = "early", | |
216 | + .write = early_console_write, | |
217 | + .flags = CON_PRINTBUFFER | CON_BOOT, | |
218 | + .index = -1 | |
219 | +}; | |
220 | + | |
193 | 221 | /* Register console for printk's, etc. */ |
194 | -int __init | |
195 | -init_etrax_debug(void) | |
222 | +int __init init_etrax_debug(void) | |
196 | 223 | { |
197 | 224 | start_port(port); |
225 | + | |
226 | + /* Register an early console if a debug port was chosen. */ | |
227 | + register_console(&early_console_dev); | |
198 | 228 | |
199 | 229 | #ifdef CONFIG_ETRAX_KGDB |
200 | 230 | start_port(kgdb_port); |
arch/cris/arch-v32/kernel/time.c
... | ... | @@ -14,6 +14,7 @@ |
14 | 14 | #include <linux/init.h> |
15 | 15 | #include <linux/threads.h> |
16 | 16 | #include <linux/cpufreq.h> |
17 | +#include <linux/mm.h> | |
17 | 18 | #include <asm/types.h> |
18 | 19 | #include <asm/signal.h> |
19 | 20 | #include <asm/io.h> |
... | ... | @@ -56,7 +57,6 @@ |
56 | 57 | } |
57 | 58 | arch_initcall(etrax_init_cont_rotime); |
58 | 59 | |
59 | - | |
60 | 60 | unsigned long timer_regs[NR_CPUS] = |
61 | 61 | { |
62 | 62 | regi_timer0, |
... | ... | @@ -68,9 +68,8 @@ |
68 | 68 | extern int set_rtc_mmss(unsigned long nowtime); |
69 | 69 | |
70 | 70 | #ifdef CONFIG_CPU_FREQ |
71 | -static int | |
72 | -cris_time_freq_notifier(struct notifier_block *nb, unsigned long val, | |
73 | - void *data); | |
71 | +static int cris_time_freq_notifier(struct notifier_block *nb, | |
72 | + unsigned long val, void *data); | |
74 | 73 | |
75 | 74 | static struct notifier_block cris_time_freq_notifier_block = { |
76 | 75 | .notifier_call = cris_time_freq_notifier, |
... | ... | @@ -87,7 +86,6 @@ |
87 | 86 | return ns; |
88 | 87 | } |
89 | 88 | |
90 | - | |
91 | 89 | /* From timer MDS describing the hardware watchdog: |
92 | 90 | * 4.3.1 Watchdog Operation |
93 | 91 | * The watchdog timer is an 8-bit timer with a configurable start value. |
94 | 92 | |
... | ... | @@ -109,11 +107,18 @@ |
109 | 107 | * is used though, so set this really low. */ |
110 | 108 | #define WATCHDOG_MIN_FREE_PAGES 8 |
111 | 109 | |
110 | +/* for reliable NICE_DOGGY behaviour */ | |
111 | +static int bite_in_progress; | |
112 | + | |
112 | 113 | void reset_watchdog(void) |
113 | 114 | { |
114 | 115 | #if defined(CONFIG_ETRAX_WATCHDOG) |
115 | 116 | reg_timer_rw_wd_ctrl wd_ctrl = { 0 }; |
116 | 117 | |
118 | +#if defined(CONFIG_ETRAX_WATCHDOG_NICE_DOGGY) | |
119 | + if (unlikely(bite_in_progress)) | |
120 | + return; | |
121 | +#endif | |
117 | 122 | /* Only keep watchdog happy as long as we have memory left! */ |
118 | 123 | if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) { |
119 | 124 | /* Reset the watchdog with the inverse of the old key */ |
120 | 125 | |
... | ... | @@ -148,7 +153,9 @@ |
148 | 153 | #if defined(CONFIG_ETRAX_WATCHDOG) |
149 | 154 | extern int cause_of_death; |
150 | 155 | |
156 | + nmi_enter(); | |
151 | 157 | oops_in_progress = 1; |
158 | + bite_in_progress = 1; | |
152 | 159 | printk(KERN_WARNING "Watchdog bite\n"); |
153 | 160 | |
154 | 161 | /* Check if forced restart or unexpected watchdog */ |
... | ... | @@ -170,6 +177,7 @@ |
170 | 177 | printk(KERN_WARNING "Oops: bitten by watchdog\n"); |
171 | 178 | show_registers(regs); |
172 | 179 | oops_in_progress = 0; |
180 | + printk("\n"); /* Flush mtdoops. */ | |
173 | 181 | #ifndef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY |
174 | 182 | reset_watchdog(); |
175 | 183 | #endif |
... | ... | @@ -202,7 +210,7 @@ |
202 | 210 | /* Reset watchdog otherwise it resets us! */ |
203 | 211 | reset_watchdog(); |
204 | 212 | |
205 | - /* Update statistics. */ | |
213 | + /* Update statistics. */ | |
206 | 214 | update_process_times(user_mode(regs)); |
207 | 215 | |
208 | 216 | cris_do_profile(regs); /* Save profiling information */ |
... | ... | @@ -213,7 +221,7 @@ |
213 | 221 | |
214 | 222 | /* Call the real timer interrupt handler */ |
215 | 223 | xtime_update(1); |
216 | - return IRQ_HANDLED; | |
224 | + return IRQ_HANDLED; | |
217 | 225 | } |
218 | 226 | |
219 | 227 | /* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain. */ |
220 | 228 | |
... | ... | @@ -293,14 +301,13 @@ |
293 | 301 | |
294 | 302 | #ifdef CONFIG_CPU_FREQ |
295 | 303 | cpufreq_register_notifier(&cris_time_freq_notifier_block, |
296 | - CPUFREQ_TRANSITION_NOTIFIER); | |
304 | + CPUFREQ_TRANSITION_NOTIFIER); | |
297 | 305 | #endif |
298 | 306 | } |
299 | 307 | |
300 | 308 | #ifdef CONFIG_CPU_FREQ |
301 | -static int | |
302 | -cris_time_freq_notifier(struct notifier_block *nb, unsigned long val, | |
303 | - void *data) | |
309 | +static int cris_time_freq_notifier(struct notifier_block *nb, | |
310 | + unsigned long val, void *data) | |
304 | 311 | { |
305 | 312 | struct cpufreq_freqs *freqs = data; |
306 | 313 | if (val == CPUFREQ_POSTCHANGE) { |
arch/cris/arch-v32/lib/usercopy.c
... | ... | @@ -26,8 +26,7 @@ |
26 | 26 | /* Copy to userspace. This is based on the memcpy used for |
27 | 27 | kernel-to-kernel copying; see "string.c". */ |
28 | 28 | |
29 | -unsigned long | |
30 | -__copy_user (void __user *pdst, const void *psrc, unsigned long pn) | |
29 | +unsigned long __copy_user(void __user *pdst, const void *psrc, unsigned long pn) | |
31 | 30 | { |
32 | 31 | /* We want the parameters put in special registers. |
33 | 32 | Make sure the compiler is able to make something useful of this. |
34 | 33 | |
... | ... | @@ -155,13 +154,13 @@ |
155 | 154 | |
156 | 155 | return retn; |
157 | 156 | } |
157 | +EXPORT_SYMBOL(__copy_user); | |
158 | 158 | |
159 | 159 | /* Copy from user to kernel, zeroing the bytes that were inaccessible in |
160 | 160 | userland. The return-value is the number of bytes that were |
161 | 161 | inaccessible. */ |
162 | - | |
163 | -unsigned long | |
164 | -__copy_user_zeroing(void *pdst, const void __user *psrc, unsigned long pn) | |
162 | +unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc, | |
163 | + unsigned long pn) | |
165 | 164 | { |
166 | 165 | /* We want the parameters put in special registers. |
167 | 166 | Make sure the compiler is able to make something useful of this. |
168 | 167 | |
... | ... | @@ -321,11 +320,10 @@ |
321 | 320 | |
322 | 321 | return retn + n; |
323 | 322 | } |
323 | +EXPORT_SYMBOL(__copy_user_zeroing); | |
324 | 324 | |
325 | 325 | /* Zero userspace. */ |
326 | - | |
327 | -unsigned long | |
328 | -__do_clear_user (void __user *pto, unsigned long pn) | |
326 | +unsigned long __do_clear_user(void __user *pto, unsigned long pn) | |
329 | 327 | { |
330 | 328 | /* We want the parameters put in special registers. |
331 | 329 | Make sure the compiler is able to make something useful of this. |
... | ... | @@ -468,4 +466,5 @@ |
468 | 466 | |
469 | 467 | return retn; |
470 | 468 | } |
469 | +EXPORT_SYMBOL(__do_clear_user); |
arch/cris/arch-v32/mach-fs/pinmux.c
... | ... | @@ -26,8 +26,30 @@ |
26 | 26 | |
27 | 27 | static void crisv32_pinmux_set(int port); |
28 | 28 | |
29 | -int crisv32_pinmux_init(void) | |
29 | +static int __crisv32_pinmux_alloc(int port, int first_pin, int last_pin, | |
30 | + enum pin_mode mode) | |
30 | 31 | { |
32 | + int i; | |
33 | + | |
34 | + for (i = first_pin; i <= last_pin; i++) { | |
35 | + if ((pins[port][i] != pinmux_none) | |
36 | + && (pins[port][i] != pinmux_gpio) | |
37 | + && (pins[port][i] != mode)) { | |
38 | +#ifdef DEBUG | |
39 | + panic("Pinmux alloc failed!\n"); | |
40 | +#endif | |
41 | + return -EPERM; | |
42 | + } | |
43 | + } | |
44 | + | |
45 | + for (i = first_pin; i <= last_pin; i++) | |
46 | + pins[port][i] = mode; | |
47 | + | |
48 | + crisv32_pinmux_set(port); | |
49 | +} | |
50 | + | |
51 | +static int crisv32_pinmux_init(void) | |
52 | +{ | |
31 | 53 | static int initialized; |
32 | 54 | |
33 | 55 | if (!initialized) { |
34 | 56 | |
35 | 57 | |
36 | 58 | |
... | ... | @@ -37,20 +59,20 @@ |
37 | 59 | pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 = |
38 | 60 | pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes; |
39 | 61 | REG_WR(pinmux, regi_pinmux, rw_pa, pa); |
40 | - crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio); | |
41 | - crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio); | |
42 | - crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio); | |
43 | - crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio); | |
62 | + __crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio); | |
63 | + __crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio); | |
64 | + __crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio); | |
65 | + __crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio); | |
44 | 66 | } |
45 | 67 | |
46 | 68 | return 0; |
47 | 69 | } |
48 | 70 | |
49 | -int | |
50 | -crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode) | |
71 | +int crisv32_pinmux_alloc(int port, int first_pin, int last_pin, | |
72 | + enum pin_mode mode) | |
51 | 73 | { |
52 | - int i; | |
53 | 74 | unsigned long flags; |
75 | + int ret; | |
54 | 76 | |
55 | 77 | crisv32_pinmux_init(); |
56 | 78 | |
57 | 79 | |
58 | 80 | |
... | ... | @@ -59,26 +81,11 @@ |
59 | 81 | |
60 | 82 | spin_lock_irqsave(&pinmux_lock, flags); |
61 | 83 | |
62 | - for (i = first_pin; i <= last_pin; i++) { | |
63 | - if ((pins[port][i] != pinmux_none) | |
64 | - && (pins[port][i] != pinmux_gpio) | |
65 | - && (pins[port][i] != mode)) { | |
66 | - spin_unlock_irqrestore(&pinmux_lock, flags); | |
67 | -#ifdef DEBUG | |
68 | - panic("Pinmux alloc failed!\n"); | |
69 | -#endif | |
70 | - return -EPERM; | |
71 | - } | |
72 | - } | |
84 | + ret = __crisv32_pinmux_alloc(port, first_pin, last_pin, mode); | |
73 | 85 | |
74 | - for (i = first_pin; i <= last_pin; i++) | |
75 | - pins[port][i] = mode; | |
76 | - | |
77 | - crisv32_pinmux_set(port); | |
78 | - | |
79 | 86 | spin_unlock_irqrestore(&pinmux_lock, flags); |
80 | 87 | |
81 | - return 0; | |
88 | + return ret; | |
82 | 89 | } |
83 | 90 | |
84 | 91 | int crisv32_pinmux_alloc_fixed(enum fixed_function function) |
85 | 92 | |
86 | 93 | |
87 | 94 | |
88 | 95 | |
89 | 96 | |
90 | 97 | |
91 | 98 | |
92 | 99 | |
93 | 100 | |
94 | 101 | |
95 | 102 | |
... | ... | @@ -98,58 +105,58 @@ |
98 | 105 | |
99 | 106 | switch (function) { |
100 | 107 | case pinmux_ser1: |
101 | - ret = crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed); | |
108 | + ret = __crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed); | |
102 | 109 | hwprot.ser1 = regk_pinmux_yes; |
103 | 110 | break; |
104 | 111 | case pinmux_ser2: |
105 | - ret = crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed); | |
112 | + ret = __crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed); | |
106 | 113 | hwprot.ser2 = regk_pinmux_yes; |
107 | 114 | break; |
108 | 115 | case pinmux_ser3: |
109 | - ret = crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed); | |
116 | + ret = __crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed); | |
110 | 117 | hwprot.ser3 = regk_pinmux_yes; |
111 | 118 | break; |
112 | 119 | case pinmux_sser0: |
113 | - ret = crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed); | |
114 | - ret |= crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed); | |
120 | + ret = __crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed); | |
121 | + ret |= __crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed); | |
115 | 122 | hwprot.sser0 = regk_pinmux_yes; |
116 | 123 | break; |
117 | 124 | case pinmux_sser1: |
118 | - ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed); | |
125 | + ret = __crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed); | |
119 | 126 | hwprot.sser1 = regk_pinmux_yes; |
120 | 127 | break; |
121 | 128 | case pinmux_ata0: |
122 | - ret = crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed); | |
123 | - ret |= crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed); | |
129 | + ret = __crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed); | |
130 | + ret |= __crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed); | |
124 | 131 | hwprot.ata0 = regk_pinmux_yes; |
125 | 132 | break; |
126 | 133 | case pinmux_ata1: |
127 | - ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed); | |
128 | - ret |= crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed); | |
134 | + ret = __crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed); | |
135 | + ret |= __crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed); | |
129 | 136 | hwprot.ata1 = regk_pinmux_yes; |
130 | 137 | break; |
131 | 138 | case pinmux_ata2: |
132 | - ret = crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed); | |
133 | - ret |= crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed); | |
139 | + ret = __crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed); | |
140 | + ret |= __crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed); | |
134 | 141 | hwprot.ata2 = regk_pinmux_yes; |
135 | 142 | break; |
136 | 143 | case pinmux_ata3: |
137 | - ret = crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed); | |
138 | - ret |= crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed); | |
144 | + ret = __crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed); | |
145 | + ret |= __crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed); | |
139 | 146 | hwprot.ata2 = regk_pinmux_yes; |
140 | 147 | break; |
141 | 148 | case pinmux_ata: |
142 | - ret = crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed); | |
143 | - ret |= crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed); | |
149 | + ret = __crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed); | |
150 | + ret |= __crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed); | |
144 | 151 | hwprot.ata = regk_pinmux_yes; |
145 | 152 | break; |
146 | 153 | case pinmux_eth1: |
147 | - ret = crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed); | |
154 | + ret = __crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed); | |
148 | 155 | hwprot.eth1 = regk_pinmux_yes; |
149 | 156 | hwprot.eth1_mgm = regk_pinmux_yes; |
150 | 157 | break; |
151 | 158 | case pinmux_timer: |
152 | - ret = crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed); | |
159 | + ret = __crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed); | |
153 | 160 | hwprot.timer = regk_pinmux_yes; |
154 | 161 | spin_unlock_irqrestore(&pinmux_lock, flags); |
155 | 162 | return ret; |
156 | 163 | |
... | ... | @@ -188,9 +195,19 @@ |
188 | 195 | #endif |
189 | 196 | } |
190 | 197 | |
191 | -int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin) | |
198 | +static int __crisv32_pinmux_dealloc(int port, int first_pin, int last_pin) | |
192 | 199 | { |
193 | 200 | int i; |
201 | + | |
202 | + for (i = first_pin; i <= last_pin; i++) | |
203 | + pins[port][i] = pinmux_none; | |
204 | + | |
205 | + crisv32_pinmux_set(port); | |
206 | + return 0; | |
207 | +} | |
208 | + | |
209 | +int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin) | |
210 | +{ | |
194 | 211 | unsigned long flags; |
195 | 212 | |
196 | 213 | crisv32_pinmux_init(); |
... | ... | @@ -199,11 +216,7 @@ |
199 | 216 | return -EINVAL; |
200 | 217 | |
201 | 218 | spin_lock_irqsave(&pinmux_lock, flags); |
202 | - | |
203 | - for (i = first_pin; i <= last_pin; i++) | |
204 | - pins[port][i] = pinmux_none; | |
205 | - | |
206 | - crisv32_pinmux_set(port); | |
219 | + __crisv32_pinmux_dealloc(port, first_pin, last_pin); | |
207 | 220 | spin_unlock_irqrestore(&pinmux_lock, flags); |
208 | 221 | |
209 | 222 | return 0; |
210 | 223 | |
211 | 224 | |
212 | 225 | |
213 | 226 | |
214 | 227 | |
215 | 228 | |
216 | 229 | |
217 | 230 | |
218 | 231 | |
219 | 232 | |
220 | 233 | |
... | ... | @@ -226,58 +239,58 @@ |
226 | 239 | |
227 | 240 | switch (function) { |
228 | 241 | case pinmux_ser1: |
229 | - ret = crisv32_pinmux_dealloc(PORT_C, 4, 7); | |
242 | + ret = __crisv32_pinmux_dealloc(PORT_C, 4, 7); | |
230 | 243 | hwprot.ser1 = regk_pinmux_no; |
231 | 244 | break; |
232 | 245 | case pinmux_ser2: |
233 | - ret = crisv32_pinmux_dealloc(PORT_C, 8, 11); | |
246 | + ret = __crisv32_pinmux_dealloc(PORT_C, 8, 11); | |
234 | 247 | hwprot.ser2 = regk_pinmux_no; |
235 | 248 | break; |
236 | 249 | case pinmux_ser3: |
237 | - ret = crisv32_pinmux_dealloc(PORT_C, 12, 15); | |
250 | + ret = __crisv32_pinmux_dealloc(PORT_C, 12, 15); | |
238 | 251 | hwprot.ser3 = regk_pinmux_no; |
239 | 252 | break; |
240 | 253 | case pinmux_sser0: |
241 | - ret = crisv32_pinmux_dealloc(PORT_C, 0, 3); | |
242 | - ret |= crisv32_pinmux_dealloc(PORT_C, 16, 16); | |
254 | + ret = __crisv32_pinmux_dealloc(PORT_C, 0, 3); | |
255 | + ret |= __crisv32_pinmux_dealloc(PORT_C, 16, 16); | |
243 | 256 | hwprot.sser0 = regk_pinmux_no; |
244 | 257 | break; |
245 | 258 | case pinmux_sser1: |
246 | - ret = crisv32_pinmux_dealloc(PORT_D, 0, 4); | |
259 | + ret = __crisv32_pinmux_dealloc(PORT_D, 0, 4); | |
247 | 260 | hwprot.sser1 = regk_pinmux_no; |
248 | 261 | break; |
249 | 262 | case pinmux_ata0: |
250 | - ret = crisv32_pinmux_dealloc(PORT_D, 5, 7); | |
251 | - ret |= crisv32_pinmux_dealloc(PORT_D, 15, 17); | |
263 | + ret = __crisv32_pinmux_dealloc(PORT_D, 5, 7); | |
264 | + ret |= __crisv32_pinmux_dealloc(PORT_D, 15, 17); | |
252 | 265 | hwprot.ata0 = regk_pinmux_no; |
253 | 266 | break; |
254 | 267 | case pinmux_ata1: |
255 | - ret = crisv32_pinmux_dealloc(PORT_D, 0, 4); | |
256 | - ret |= crisv32_pinmux_dealloc(PORT_E, 17, 17); | |
268 | + ret = __crisv32_pinmux_dealloc(PORT_D, 0, 4); | |
269 | + ret |= __crisv32_pinmux_dealloc(PORT_E, 17, 17); | |
257 | 270 | hwprot.ata1 = regk_pinmux_no; |
258 | 271 | break; |
259 | 272 | case pinmux_ata2: |
260 | - ret = crisv32_pinmux_dealloc(PORT_C, 11, 15); | |
261 | - ret |= crisv32_pinmux_dealloc(PORT_E, 3, 3); | |
273 | + ret = __crisv32_pinmux_dealloc(PORT_C, 11, 15); | |
274 | + ret |= __crisv32_pinmux_dealloc(PORT_E, 3, 3); | |
262 | 275 | hwprot.ata2 = regk_pinmux_no; |
263 | 276 | break; |
264 | 277 | case pinmux_ata3: |
265 | - ret = crisv32_pinmux_dealloc(PORT_C, 8, 10); | |
266 | - ret |= crisv32_pinmux_dealloc(PORT_C, 0, 2); | |
278 | + ret = __crisv32_pinmux_dealloc(PORT_C, 8, 10); | |
279 | + ret |= __crisv32_pinmux_dealloc(PORT_C, 0, 2); | |
267 | 280 | hwprot.ata2 = regk_pinmux_no; |
268 | 281 | break; |
269 | 282 | case pinmux_ata: |
270 | - ret = crisv32_pinmux_dealloc(PORT_B, 0, 15); | |
271 | - ret |= crisv32_pinmux_dealloc(PORT_D, 8, 15); | |
283 | + ret = __crisv32_pinmux_dealloc(PORT_B, 0, 15); | |
284 | + ret |= __crisv32_pinmux_dealloc(PORT_D, 8, 15); | |
272 | 285 | hwprot.ata = regk_pinmux_no; |
273 | 286 | break; |
274 | 287 | case pinmux_eth1: |
275 | - ret = crisv32_pinmux_dealloc(PORT_E, 0, 17); | |
288 | + ret = __crisv32_pinmux_dealloc(PORT_E, 0, 17); | |
276 | 289 | hwprot.eth1 = regk_pinmux_no; |
277 | 290 | hwprot.eth1_mgm = regk_pinmux_no; |
278 | 291 | break; |
279 | 292 | case pinmux_timer: |
280 | - ret = crisv32_pinmux_dealloc(PORT_C, 16, 16); | |
293 | + ret = __crisv32_pinmux_dealloc(PORT_C, 16, 16); | |
281 | 294 | hwprot.timer = regk_pinmux_no; |
282 | 295 | spin_unlock_irqrestore(&pinmux_lock, flags); |
283 | 296 | return ret; |
... | ... | @@ -293,7 +306,8 @@ |
293 | 306 | return ret; |
294 | 307 | } |
295 | 308 | |
296 | -void crisv32_pinmux_dump(void) | |
309 | +#ifdef DEBUG | |
310 | +static void crisv32_pinmux_dump(void) | |
297 | 311 | { |
298 | 312 | int i, j; |
299 | 313 | |
... | ... | @@ -305,6 +319,6 @@ |
305 | 319 | printk(KERN_DEBUG " Pin %d = %d\n", j, pins[i][j]); |
306 | 320 | } |
307 | 321 | } |
308 | - | |
322 | +#endif | |
309 | 323 | __initcall(crisv32_pinmux_init); |
arch/cris/include/arch-v32/mach-fs/mach/pinmux.h
... | ... | @@ -28,12 +28,10 @@ |
28 | 28 | pinmux_timer |
29 | 29 | }; |
30 | 30 | |
31 | -int crisv32_pinmux_init(void); | |
32 | 31 | int crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode); |
33 | 32 | int crisv32_pinmux_alloc_fixed(enum fixed_function function); |
34 | 33 | int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin); |
35 | 34 | int crisv32_pinmux_dealloc_fixed(enum fixed_function function); |
36 | -void crisv32_pinmux_dump(void); | |
37 | 35 | |
38 | 36 | #endif |
arch/cris/include/asm/Kbuild
arch/cris/include/uapi/asm/Kbuild
arch/cris/kernel/crisksyms.c
... | ... | @@ -47,16 +47,16 @@ |
47 | 47 | EXPORT_SYMBOL(__ioremap); |
48 | 48 | EXPORT_SYMBOL(iounmap); |
49 | 49 | |
50 | -/* Userspace access functions */ | |
51 | -EXPORT_SYMBOL(__copy_user_zeroing); | |
52 | -EXPORT_SYMBOL(__copy_user); | |
53 | - | |
54 | 50 | #undef memcpy |
55 | 51 | #undef memset |
56 | 52 | extern void * memset(void *, int, __kernel_size_t); |
57 | 53 | extern void * memcpy(void *, const void *, __kernel_size_t); |
58 | 54 | EXPORT_SYMBOL(memcpy); |
59 | 55 | EXPORT_SYMBOL(memset); |
56 | +#ifdef CONFIG_ETRAX_ARCH_V32 | |
57 | +#undef strcmp | |
58 | +EXPORT_SYMBOL(strcmp); | |
59 | +#endif | |
60 | 60 | |
61 | 61 | #ifdef CONFIG_ETRAX_FAST_TIMER |
62 | 62 | /* Fast timer functions */ |
... | ... | @@ -66,4 +66,5 @@ |
66 | 66 | EXPORT_SYMBOL(schedule_usleep); |
67 | 67 | #endif |
68 | 68 | EXPORT_SYMBOL(csum_partial); |
69 | +EXPORT_SYMBOL(csum_partial_copy_from_user); |
arch/cris/kernel/traps.c
... | ... | @@ -14,6 +14,10 @@ |
14 | 14 | |
15 | 15 | #include <linux/init.h> |
16 | 16 | #include <linux/module.h> |
17 | +#include <linux/utsname.h> | |
18 | +#ifdef CONFIG_KALLSYMS | |
19 | +#include <linux/kallsyms.h> | |
20 | +#endif | |
17 | 21 | |
18 | 22 | #include <asm/pgtable.h> |
19 | 23 | #include <asm/uaccess.h> |
20 | 24 | |
21 | 25 | |
22 | 26 | |
... | ... | @@ -34,25 +38,24 @@ |
34 | 38 | |
35 | 39 | void (*nmi_handler)(struct pt_regs *); |
36 | 40 | |
37 | -void | |
38 | -show_trace(unsigned long *stack) | |
41 | +void show_trace(unsigned long *stack) | |
39 | 42 | { |
40 | 43 | unsigned long addr, module_start, module_end; |
41 | 44 | extern char _stext, _etext; |
42 | 45 | int i; |
43 | 46 | |
44 | - printk("\nCall Trace: "); | |
47 | + pr_err("\nCall Trace: "); | |
45 | 48 | |
46 | 49 | i = 1; |
47 | 50 | module_start = VMALLOC_START; |
48 | 51 | module_end = VMALLOC_END; |
49 | 52 | |
50 | - while (((long)stack & (THREAD_SIZE-1)) != 0) { | |
53 | + while (((long)stack & (THREAD_SIZE - 1)) != 0) { | |
51 | 54 | if (__get_user(addr, stack)) { |
52 | 55 | /* This message matches "failing address" marked |
53 | 56 | s390 in ksymoops, so lines containing it will |
54 | 57 | not be filtered out by ksymoops. */ |
55 | - printk("Failing address 0x%lx\n", (unsigned long)stack); | |
58 | + pr_err("Failing address 0x%lx\n", (unsigned long)stack); | |
56 | 59 | break; |
57 | 60 | } |
58 | 61 | stack++; |
59 | 62 | |
60 | 63 | |
... | ... | @@ -68,10 +71,14 @@ |
68 | 71 | if (((addr >= (unsigned long)&_stext) && |
69 | 72 | (addr <= (unsigned long)&_etext)) || |
70 | 73 | ((addr >= module_start) && (addr <= module_end))) { |
74 | +#ifdef CONFIG_KALLSYMS | |
75 | + print_ip_sym(addr); | |
76 | +#else | |
71 | 77 | if (i && ((i % 8) == 0)) |
72 | - printk("\n "); | |
73 | - printk("[<%08lx>] ", addr); | |
78 | + pr_err("\n "); | |
79 | + pr_err("[<%08lx>] ", addr); | |
74 | 80 | i++; |
81 | +#endif | |
75 | 82 | } |
76 | 83 | } |
77 | 84 | } |
78 | 85 | |
79 | 86 | |
80 | 87 | |
... | ... | @@ -111,21 +118,21 @@ |
111 | 118 | |
112 | 119 | stack = sp; |
113 | 120 | |
114 | - printk("\nStack from %08lx:\n ", (unsigned long)stack); | |
121 | + pr_err("\nStack from %08lx:\n ", (unsigned long)stack); | |
115 | 122 | for (i = 0; i < kstack_depth_to_print; i++) { |
116 | 123 | if (((long)stack & (THREAD_SIZE-1)) == 0) |
117 | 124 | break; |
118 | 125 | if (i && ((i % 8) == 0)) |
119 | - printk("\n "); | |
126 | + pr_err("\n "); | |
120 | 127 | if (__get_user(addr, stack)) { |
121 | 128 | /* This message matches "failing address" marked |
122 | 129 | s390 in ksymoops, so lines containing it will |
123 | 130 | not be filtered out by ksymoops. */ |
124 | - printk("Failing address 0x%lx\n", (unsigned long)stack); | |
131 | + pr_err("Failing address 0x%lx\n", (unsigned long)stack); | |
125 | 132 | break; |
126 | 133 | } |
127 | 134 | stack++; |
128 | - printk("%08lx ", addr); | |
135 | + pr_err("%08lx ", addr); | |
129 | 136 | } |
130 | 137 | show_trace(sp); |
131 | 138 | } |
132 | 139 | |
133 | 140 | |
134 | 141 | |
135 | 142 | |
136 | 143 | |
137 | 144 | |
... | ... | @@ -139,33 +146,32 @@ |
139 | 146 | unsigned long *sp = (unsigned long *)rdusp(); |
140 | 147 | int i; |
141 | 148 | |
142 | - printk("Stack dump [0x%08lx]:\n", (unsigned long)sp); | |
149 | + pr_err("Stack dump [0x%08lx]:\n", (unsigned long)sp); | |
143 | 150 | for (i = 0; i < 16; i++) |
144 | - printk("sp + %d: 0x%08lx\n", i*4, sp[i]); | |
151 | + pr_err("sp + %d: 0x%08lx\n", i*4, sp[i]); | |
145 | 152 | return 0; |
146 | 153 | } |
147 | 154 | #endif |
148 | 155 | |
149 | -void | |
150 | -set_nmi_handler(void (*handler)(struct pt_regs *)) | |
156 | +void set_nmi_handler(void (*handler)(struct pt_regs *)) | |
151 | 157 | { |
152 | 158 | nmi_handler = handler; |
153 | 159 | arch_enable_nmi(); |
154 | 160 | } |
155 | 161 | |
156 | 162 | #ifdef CONFIG_DEBUG_NMI_OOPS |
157 | -void | |
158 | -oops_nmi_handler(struct pt_regs *regs) | |
163 | +void oops_nmi_handler(struct pt_regs *regs) | |
159 | 164 | { |
160 | 165 | stop_watchdog(); |
161 | 166 | oops_in_progress = 1; |
162 | - printk("NMI!\n"); | |
167 | + pr_err("NMI!\n"); | |
163 | 168 | show_registers(regs); |
164 | 169 | oops_in_progress = 0; |
170 | + oops_exit(); | |
171 | + pr_err("\n"); /* Flush mtdoops. */ | |
165 | 172 | } |
166 | 173 | |
167 | -static int __init | |
168 | -oops_nmi_register(void) | |
174 | +static int __init oops_nmi_register(void) | |
169 | 175 | { |
170 | 176 | set_nmi_handler(oops_nmi_handler); |
171 | 177 | return 0; |
... | ... | @@ -180,8 +186,7 @@ |
180 | 186 | * similar to an Oops dump, and if the kernel is configured to be a nice |
181 | 187 | * doggy, then halt instead of reboot. |
182 | 188 | */ |
183 | -void | |
184 | -watchdog_bite_hook(struct pt_regs *regs) | |
189 | +void watchdog_bite_hook(struct pt_regs *regs) | |
185 | 190 | { |
186 | 191 | #ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY |
187 | 192 | local_irq_disable(); |
... | ... | @@ -196,8 +201,7 @@ |
196 | 201 | } |
197 | 202 | |
198 | 203 | /* This is normally the Oops function. */ |
199 | -void | |
200 | -die_if_kernel(const char *str, struct pt_regs *regs, long err) | |
204 | +void die_if_kernel(const char *str, struct pt_regs *regs, long err) | |
201 | 205 | { |
202 | 206 | if (user_mode(regs)) |
203 | 207 | return; |
204 | 208 | |
205 | 209 | |
206 | 210 | |
... | ... | @@ -211,13 +215,17 @@ |
211 | 215 | stop_watchdog(); |
212 | 216 | #endif |
213 | 217 | |
218 | + oops_enter(); | |
214 | 219 | handle_BUG(regs); |
215 | 220 | |
216 | - printk("%s: %04lx\n", str, err & 0xffff); | |
221 | + pr_err("Linux %s %s\n", utsname()->release, utsname()->version); | |
222 | + pr_err("%s: %04lx\n", str, err & 0xffff); | |
217 | 223 | |
218 | 224 | show_registers(regs); |
219 | 225 | |
226 | + oops_exit(); | |
220 | 227 | oops_in_progress = 0; |
228 | + pr_err("\n"); /* Flush mtdoops. */ | |
221 | 229 | |
222 | 230 | #ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY |
223 | 231 | reset_watchdog(); |
... | ... | @@ -225,8 +233,7 @@ |
225 | 233 | do_exit(SIGSEGV); |
226 | 234 | } |
227 | 235 | |
228 | -void __init | |
229 | -trap_init(void) | |
236 | +void __init trap_init(void) | |
230 | 237 | { |
231 | 238 | /* Nothing needs to be done */ |
232 | 239 | } |
arch/cris/mm/init.c
... | ... | @@ -11,13 +11,15 @@ |
11 | 11 | #include <linux/gfp.h> |
12 | 12 | #include <linux/init.h> |
13 | 13 | #include <linux/bootmem.h> |
14 | +#include <linux/proc_fs.h> | |
15 | +#include <linux/kcore.h> | |
14 | 16 | #include <asm/tlb.h> |
15 | 17 | #include <asm/sections.h> |
16 | 18 | |
17 | 19 | unsigned long empty_zero_page; |
20 | +EXPORT_SYMBOL(empty_zero_page); | |
18 | 21 | |
19 | -void __init | |
20 | -mem_init(void) | |
22 | +void __init mem_init(void) | |
21 | 23 | { |
22 | 24 | BUG_ON(!mem_map); |
23 | 25 | |
24 | 26 | |
25 | 27 | |
26 | 28 | |
... | ... | @@ -31,11 +33,37 @@ |
31 | 33 | mem_init_print_info(NULL); |
32 | 34 | } |
33 | 35 | |
34 | -/* free the pages occupied by initialization code */ | |
36 | +/* Free a range of init pages. Virtual addresses. */ | |
35 | 37 | |
36 | -void | |
37 | -free_initmem(void) | |
38 | +void free_init_pages(const char *what, unsigned long begin, unsigned long end) | |
38 | 39 | { |
40 | + unsigned long addr; | |
41 | + | |
42 | + for (addr = begin; addr < end; addr += PAGE_SIZE) { | |
43 | + ClearPageReserved(virt_to_page(addr)); | |
44 | + init_page_count(virt_to_page(addr)); | |
45 | + free_page(addr); | |
46 | + totalram_pages++; | |
47 | + } | |
48 | + | |
49 | + printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10); | |
50 | +} | |
51 | + | |
52 | +/* Free the pages occupied by initialization code. */ | |
53 | + | |
54 | +void free_initmem(void) | |
55 | +{ | |
39 | 56 | free_initmem_default(-1); |
40 | 57 | } |
58 | + | |
59 | +/* Free the pages occupied by initrd code. */ | |
60 | + | |
61 | +#ifdef CONFIG_BLK_DEV_INITRD | |
62 | +void free_initrd_mem(unsigned long start, unsigned long end) | |
63 | +{ | |
64 | + free_init_pages("initrd memory", | |
65 | + start, | |
66 | + end); | |
67 | +} | |
68 | +#endif |
arch/cris/mm/ioremap.c
... | ... | @@ -76,10 +76,11 @@ |
76 | 76 | * Must be freed with iounmap. |
77 | 77 | */ |
78 | 78 | |
79 | -void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size) | |
79 | +void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size) | |
80 | 80 | { |
81 | 81 | return __ioremap(phys_addr | MEM_NON_CACHEABLE, size, 0); |
82 | 82 | } |
83 | +EXPORT_SYMBOL(ioremap_nocache); | |
83 | 84 | |
84 | 85 | void iounmap(volatile void __iomem *addr) |
85 | 86 | { |