Commit 0eb8880fac7b0f32ebab33f99e758c6b308e3aa1
Committed by
Grant Likely
1 parent
d5a8003135
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
spi/spi-sh: add IORESOURCE_MEM_TYPE_MASK decoding for access size
This SPI controller's access size is 32, or 8-bit. The previous driver supported 32-bit only. So, this patch adds IORESOURCE_MEM_TYPE_MASK decoding, an then, the driver can handle the SPI controller of 8-bit. Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Showing 1 changed file with 23 additions and 2 deletions Inline Diff
drivers/spi/spi-sh.c
1 | /* | 1 | /* |
2 | * SH SPI bus driver | 2 | * SH SPI bus driver |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Renesas Solutions Corp. | 4 | * Copyright (C) 2011 Renesas Solutions Corp. |
5 | * | 5 | * |
6 | * Based on pxa2xx_spi.c: | 6 | * Based on pxa2xx_spi.c: |
7 | * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs | 7 | * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
11 | * the Free Software Foundation; version 2 of the License. | 11 | * the Free Software Foundation; version 2 of the License. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
28 | #include <linux/timer.h> | 28 | #include <linux/timer.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/list.h> | 30 | #include <linux/list.h> |
31 | #include <linux/workqueue.h> | 31 | #include <linux/workqueue.h> |
32 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
33 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
34 | #include <linux/io.h> | 34 | #include <linux/io.h> |
35 | #include <linux/spi/spi.h> | 35 | #include <linux/spi/spi.h> |
36 | 36 | ||
37 | #define SPI_SH_TBR 0x00 | 37 | #define SPI_SH_TBR 0x00 |
38 | #define SPI_SH_RBR 0x00 | 38 | #define SPI_SH_RBR 0x00 |
39 | #define SPI_SH_CR1 0x08 | 39 | #define SPI_SH_CR1 0x08 |
40 | #define SPI_SH_CR2 0x10 | 40 | #define SPI_SH_CR2 0x10 |
41 | #define SPI_SH_CR3 0x18 | 41 | #define SPI_SH_CR3 0x18 |
42 | #define SPI_SH_CR4 0x20 | 42 | #define SPI_SH_CR4 0x20 |
43 | #define SPI_SH_CR5 0x28 | 43 | #define SPI_SH_CR5 0x28 |
44 | 44 | ||
45 | /* CR1 */ | 45 | /* CR1 */ |
46 | #define SPI_SH_TBE 0x80 | 46 | #define SPI_SH_TBE 0x80 |
47 | #define SPI_SH_TBF 0x40 | 47 | #define SPI_SH_TBF 0x40 |
48 | #define SPI_SH_RBE 0x20 | 48 | #define SPI_SH_RBE 0x20 |
49 | #define SPI_SH_RBF 0x10 | 49 | #define SPI_SH_RBF 0x10 |
50 | #define SPI_SH_PFONRD 0x08 | 50 | #define SPI_SH_PFONRD 0x08 |
51 | #define SPI_SH_SSDB 0x04 | 51 | #define SPI_SH_SSDB 0x04 |
52 | #define SPI_SH_SSD 0x02 | 52 | #define SPI_SH_SSD 0x02 |
53 | #define SPI_SH_SSA 0x01 | 53 | #define SPI_SH_SSA 0x01 |
54 | 54 | ||
55 | /* CR2 */ | 55 | /* CR2 */ |
56 | #define SPI_SH_RSTF 0x80 | 56 | #define SPI_SH_RSTF 0x80 |
57 | #define SPI_SH_LOOPBK 0x40 | 57 | #define SPI_SH_LOOPBK 0x40 |
58 | #define SPI_SH_CPOL 0x20 | 58 | #define SPI_SH_CPOL 0x20 |
59 | #define SPI_SH_CPHA 0x10 | 59 | #define SPI_SH_CPHA 0x10 |
60 | #define SPI_SH_L1M0 0x08 | 60 | #define SPI_SH_L1M0 0x08 |
61 | 61 | ||
62 | /* CR3 */ | 62 | /* CR3 */ |
63 | #define SPI_SH_MAX_BYTE 0xFF | 63 | #define SPI_SH_MAX_BYTE 0xFF |
64 | 64 | ||
65 | /* CR4 */ | 65 | /* CR4 */ |
66 | #define SPI_SH_TBEI 0x80 | 66 | #define SPI_SH_TBEI 0x80 |
67 | #define SPI_SH_TBFI 0x40 | 67 | #define SPI_SH_TBFI 0x40 |
68 | #define SPI_SH_RBEI 0x20 | 68 | #define SPI_SH_RBEI 0x20 |
69 | #define SPI_SH_RBFI 0x10 | 69 | #define SPI_SH_RBFI 0x10 |
70 | #define SPI_SH_WPABRT 0x04 | 70 | #define SPI_SH_WPABRT 0x04 |
71 | #define SPI_SH_SSS 0x01 | 71 | #define SPI_SH_SSS 0x01 |
72 | 72 | ||
73 | /* CR8 */ | 73 | /* CR8 */ |
74 | #define SPI_SH_P1L0 0x80 | 74 | #define SPI_SH_P1L0 0x80 |
75 | #define SPI_SH_PP1L0 0x40 | 75 | #define SPI_SH_PP1L0 0x40 |
76 | #define SPI_SH_MUXI 0x20 | 76 | #define SPI_SH_MUXI 0x20 |
77 | #define SPI_SH_MUXIRQ 0x10 | 77 | #define SPI_SH_MUXIRQ 0x10 |
78 | 78 | ||
79 | #define SPI_SH_FIFO_SIZE 32 | 79 | #define SPI_SH_FIFO_SIZE 32 |
80 | #define SPI_SH_SEND_TIMEOUT (3 * HZ) | 80 | #define SPI_SH_SEND_TIMEOUT (3 * HZ) |
81 | #define SPI_SH_RECEIVE_TIMEOUT (HZ >> 3) | 81 | #define SPI_SH_RECEIVE_TIMEOUT (HZ >> 3) |
82 | 82 | ||
83 | #undef DEBUG | 83 | #undef DEBUG |
84 | 84 | ||
85 | struct spi_sh_data { | 85 | struct spi_sh_data { |
86 | void __iomem *addr; | 86 | void __iomem *addr; |
87 | int irq; | 87 | int irq; |
88 | struct spi_master *master; | 88 | struct spi_master *master; |
89 | struct list_head queue; | 89 | struct list_head queue; |
90 | struct workqueue_struct *workqueue; | 90 | struct workqueue_struct *workqueue; |
91 | struct work_struct ws; | 91 | struct work_struct ws; |
92 | unsigned long cr1; | 92 | unsigned long cr1; |
93 | wait_queue_head_t wait; | 93 | wait_queue_head_t wait; |
94 | spinlock_t lock; | 94 | spinlock_t lock; |
95 | int width; | ||
95 | }; | 96 | }; |
96 | 97 | ||
97 | static void spi_sh_write(struct spi_sh_data *ss, unsigned long data, | 98 | static void spi_sh_write(struct spi_sh_data *ss, unsigned long data, |
98 | unsigned long offset) | 99 | unsigned long offset) |
99 | { | 100 | { |
100 | writel(data, ss->addr + offset); | 101 | if (ss->width == 8) |
102 | iowrite8(data, ss->addr + (offset >> 2)); | ||
103 | else if (ss->width == 32) | ||
104 | iowrite32(data, ss->addr + offset); | ||
101 | } | 105 | } |
102 | 106 | ||
103 | static unsigned long spi_sh_read(struct spi_sh_data *ss, unsigned long offset) | 107 | static unsigned long spi_sh_read(struct spi_sh_data *ss, unsigned long offset) |
104 | { | 108 | { |
105 | return readl(ss->addr + offset); | 109 | if (ss->width == 8) |
110 | return ioread8(ss->addr + (offset >> 2)); | ||
111 | else if (ss->width == 32) | ||
112 | return ioread32(ss->addr + offset); | ||
113 | else | ||
114 | return 0; | ||
106 | } | 115 | } |
107 | 116 | ||
108 | static void spi_sh_set_bit(struct spi_sh_data *ss, unsigned long val, | 117 | static void spi_sh_set_bit(struct spi_sh_data *ss, unsigned long val, |
109 | unsigned long offset) | 118 | unsigned long offset) |
110 | { | 119 | { |
111 | unsigned long tmp; | 120 | unsigned long tmp; |
112 | 121 | ||
113 | tmp = spi_sh_read(ss, offset); | 122 | tmp = spi_sh_read(ss, offset); |
114 | tmp |= val; | 123 | tmp |= val; |
115 | spi_sh_write(ss, tmp, offset); | 124 | spi_sh_write(ss, tmp, offset); |
116 | } | 125 | } |
117 | 126 | ||
118 | static void spi_sh_clear_bit(struct spi_sh_data *ss, unsigned long val, | 127 | static void spi_sh_clear_bit(struct spi_sh_data *ss, unsigned long val, |
119 | unsigned long offset) | 128 | unsigned long offset) |
120 | { | 129 | { |
121 | unsigned long tmp; | 130 | unsigned long tmp; |
122 | 131 | ||
123 | tmp = spi_sh_read(ss, offset); | 132 | tmp = spi_sh_read(ss, offset); |
124 | tmp &= ~val; | 133 | tmp &= ~val; |
125 | spi_sh_write(ss, tmp, offset); | 134 | spi_sh_write(ss, tmp, offset); |
126 | } | 135 | } |
127 | 136 | ||
128 | static void clear_fifo(struct spi_sh_data *ss) | 137 | static void clear_fifo(struct spi_sh_data *ss) |
129 | { | 138 | { |
130 | spi_sh_set_bit(ss, SPI_SH_RSTF, SPI_SH_CR2); | 139 | spi_sh_set_bit(ss, SPI_SH_RSTF, SPI_SH_CR2); |
131 | spi_sh_clear_bit(ss, SPI_SH_RSTF, SPI_SH_CR2); | 140 | spi_sh_clear_bit(ss, SPI_SH_RSTF, SPI_SH_CR2); |
132 | } | 141 | } |
133 | 142 | ||
134 | static int spi_sh_wait_receive_buffer(struct spi_sh_data *ss) | 143 | static int spi_sh_wait_receive_buffer(struct spi_sh_data *ss) |
135 | { | 144 | { |
136 | int timeout = 100000; | 145 | int timeout = 100000; |
137 | 146 | ||
138 | while (spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) { | 147 | while (spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) { |
139 | udelay(10); | 148 | udelay(10); |
140 | if (timeout-- < 0) | 149 | if (timeout-- < 0) |
141 | return -ETIMEDOUT; | 150 | return -ETIMEDOUT; |
142 | } | 151 | } |
143 | return 0; | 152 | return 0; |
144 | } | 153 | } |
145 | 154 | ||
146 | static int spi_sh_wait_write_buffer_empty(struct spi_sh_data *ss) | 155 | static int spi_sh_wait_write_buffer_empty(struct spi_sh_data *ss) |
147 | { | 156 | { |
148 | int timeout = 100000; | 157 | int timeout = 100000; |
149 | 158 | ||
150 | while (!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBE)) { | 159 | while (!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBE)) { |
151 | udelay(10); | 160 | udelay(10); |
152 | if (timeout-- < 0) | 161 | if (timeout-- < 0) |
153 | return -ETIMEDOUT; | 162 | return -ETIMEDOUT; |
154 | } | 163 | } |
155 | return 0; | 164 | return 0; |
156 | } | 165 | } |
157 | 166 | ||
158 | static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg, | 167 | static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg, |
159 | struct spi_transfer *t) | 168 | struct spi_transfer *t) |
160 | { | 169 | { |
161 | int i, retval = 0; | 170 | int i, retval = 0; |
162 | int remain = t->len; | 171 | int remain = t->len; |
163 | int cur_len; | 172 | int cur_len; |
164 | unsigned char *data; | 173 | unsigned char *data; |
165 | unsigned long tmp; | 174 | unsigned long tmp; |
166 | long ret; | 175 | long ret; |
167 | 176 | ||
168 | if (t->len) | 177 | if (t->len) |
169 | spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); | 178 | spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); |
170 | 179 | ||
171 | data = (unsigned char *)t->tx_buf; | 180 | data = (unsigned char *)t->tx_buf; |
172 | while (remain > 0) { | 181 | while (remain > 0) { |
173 | cur_len = min(SPI_SH_FIFO_SIZE, remain); | 182 | cur_len = min(SPI_SH_FIFO_SIZE, remain); |
174 | for (i = 0; i < cur_len && | 183 | for (i = 0; i < cur_len && |
175 | !(spi_sh_read(ss, SPI_SH_CR4) & | 184 | !(spi_sh_read(ss, SPI_SH_CR4) & |
176 | SPI_SH_WPABRT) && | 185 | SPI_SH_WPABRT) && |
177 | !(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBF); | 186 | !(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBF); |
178 | i++) | 187 | i++) |
179 | spi_sh_write(ss, (unsigned long)data[i], SPI_SH_TBR); | 188 | spi_sh_write(ss, (unsigned long)data[i], SPI_SH_TBR); |
180 | 189 | ||
181 | if (spi_sh_read(ss, SPI_SH_CR4) & SPI_SH_WPABRT) { | 190 | if (spi_sh_read(ss, SPI_SH_CR4) & SPI_SH_WPABRT) { |
182 | /* Abort SPI operation */ | 191 | /* Abort SPI operation */ |
183 | spi_sh_set_bit(ss, SPI_SH_WPABRT, SPI_SH_CR4); | 192 | spi_sh_set_bit(ss, SPI_SH_WPABRT, SPI_SH_CR4); |
184 | retval = -EIO; | 193 | retval = -EIO; |
185 | break; | 194 | break; |
186 | } | 195 | } |
187 | 196 | ||
188 | cur_len = i; | 197 | cur_len = i; |
189 | 198 | ||
190 | remain -= cur_len; | 199 | remain -= cur_len; |
191 | data += cur_len; | 200 | data += cur_len; |
192 | 201 | ||
193 | if (remain > 0) { | 202 | if (remain > 0) { |
194 | ss->cr1 &= ~SPI_SH_TBE; | 203 | ss->cr1 &= ~SPI_SH_TBE; |
195 | spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4); | 204 | spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4); |
196 | ret = wait_event_interruptible_timeout(ss->wait, | 205 | ret = wait_event_interruptible_timeout(ss->wait, |
197 | ss->cr1 & SPI_SH_TBE, | 206 | ss->cr1 & SPI_SH_TBE, |
198 | SPI_SH_SEND_TIMEOUT); | 207 | SPI_SH_SEND_TIMEOUT); |
199 | if (ret == 0 && !(ss->cr1 & SPI_SH_TBE)) { | 208 | if (ret == 0 && !(ss->cr1 & SPI_SH_TBE)) { |
200 | printk(KERN_ERR "%s: timeout\n", __func__); | 209 | printk(KERN_ERR "%s: timeout\n", __func__); |
201 | return -ETIMEDOUT; | 210 | return -ETIMEDOUT; |
202 | } | 211 | } |
203 | } | 212 | } |
204 | } | 213 | } |
205 | 214 | ||
206 | if (list_is_last(&t->transfer_list, &mesg->transfers)) { | 215 | if (list_is_last(&t->transfer_list, &mesg->transfers)) { |
207 | tmp = spi_sh_read(ss, SPI_SH_CR1); | 216 | tmp = spi_sh_read(ss, SPI_SH_CR1); |
208 | tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB); | 217 | tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB); |
209 | spi_sh_write(ss, tmp, SPI_SH_CR1); | 218 | spi_sh_write(ss, tmp, SPI_SH_CR1); |
210 | spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); | 219 | spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); |
211 | 220 | ||
212 | ss->cr1 &= ~SPI_SH_TBE; | 221 | ss->cr1 &= ~SPI_SH_TBE; |
213 | spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4); | 222 | spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4); |
214 | ret = wait_event_interruptible_timeout(ss->wait, | 223 | ret = wait_event_interruptible_timeout(ss->wait, |
215 | ss->cr1 & SPI_SH_TBE, | 224 | ss->cr1 & SPI_SH_TBE, |
216 | SPI_SH_SEND_TIMEOUT); | 225 | SPI_SH_SEND_TIMEOUT); |
217 | if (ret == 0 && (ss->cr1 & SPI_SH_TBE)) { | 226 | if (ret == 0 && (ss->cr1 & SPI_SH_TBE)) { |
218 | printk(KERN_ERR "%s: timeout\n", __func__); | 227 | printk(KERN_ERR "%s: timeout\n", __func__); |
219 | return -ETIMEDOUT; | 228 | return -ETIMEDOUT; |
220 | } | 229 | } |
221 | } | 230 | } |
222 | 231 | ||
223 | return retval; | 232 | return retval; |
224 | } | 233 | } |
225 | 234 | ||
226 | static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg, | 235 | static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg, |
227 | struct spi_transfer *t) | 236 | struct spi_transfer *t) |
228 | { | 237 | { |
229 | int i; | 238 | int i; |
230 | int remain = t->len; | 239 | int remain = t->len; |
231 | int cur_len; | 240 | int cur_len; |
232 | unsigned char *data; | 241 | unsigned char *data; |
233 | unsigned long tmp; | 242 | unsigned long tmp; |
234 | long ret; | 243 | long ret; |
235 | 244 | ||
236 | if (t->len > SPI_SH_MAX_BYTE) | 245 | if (t->len > SPI_SH_MAX_BYTE) |
237 | spi_sh_write(ss, SPI_SH_MAX_BYTE, SPI_SH_CR3); | 246 | spi_sh_write(ss, SPI_SH_MAX_BYTE, SPI_SH_CR3); |
238 | else | 247 | else |
239 | spi_sh_write(ss, t->len, SPI_SH_CR3); | 248 | spi_sh_write(ss, t->len, SPI_SH_CR3); |
240 | 249 | ||
241 | tmp = spi_sh_read(ss, SPI_SH_CR1); | 250 | tmp = spi_sh_read(ss, SPI_SH_CR1); |
242 | tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB); | 251 | tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB); |
243 | spi_sh_write(ss, tmp, SPI_SH_CR1); | 252 | spi_sh_write(ss, tmp, SPI_SH_CR1); |
244 | spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); | 253 | spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); |
245 | 254 | ||
246 | spi_sh_wait_write_buffer_empty(ss); | 255 | spi_sh_wait_write_buffer_empty(ss); |
247 | 256 | ||
248 | data = (unsigned char *)t->rx_buf; | 257 | data = (unsigned char *)t->rx_buf; |
249 | while (remain > 0) { | 258 | while (remain > 0) { |
250 | if (remain >= SPI_SH_FIFO_SIZE) { | 259 | if (remain >= SPI_SH_FIFO_SIZE) { |
251 | ss->cr1 &= ~SPI_SH_RBF; | 260 | ss->cr1 &= ~SPI_SH_RBF; |
252 | spi_sh_set_bit(ss, SPI_SH_RBF, SPI_SH_CR4); | 261 | spi_sh_set_bit(ss, SPI_SH_RBF, SPI_SH_CR4); |
253 | ret = wait_event_interruptible_timeout(ss->wait, | 262 | ret = wait_event_interruptible_timeout(ss->wait, |
254 | ss->cr1 & SPI_SH_RBF, | 263 | ss->cr1 & SPI_SH_RBF, |
255 | SPI_SH_RECEIVE_TIMEOUT); | 264 | SPI_SH_RECEIVE_TIMEOUT); |
256 | if (ret == 0 && | 265 | if (ret == 0 && |
257 | spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) { | 266 | spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) { |
258 | printk(KERN_ERR "%s: timeout\n", __func__); | 267 | printk(KERN_ERR "%s: timeout\n", __func__); |
259 | return -ETIMEDOUT; | 268 | return -ETIMEDOUT; |
260 | } | 269 | } |
261 | } | 270 | } |
262 | 271 | ||
263 | cur_len = min(SPI_SH_FIFO_SIZE, remain); | 272 | cur_len = min(SPI_SH_FIFO_SIZE, remain); |
264 | for (i = 0; i < cur_len; i++) { | 273 | for (i = 0; i < cur_len; i++) { |
265 | if (spi_sh_wait_receive_buffer(ss)) | 274 | if (spi_sh_wait_receive_buffer(ss)) |
266 | break; | 275 | break; |
267 | data[i] = (unsigned char)spi_sh_read(ss, SPI_SH_RBR); | 276 | data[i] = (unsigned char)spi_sh_read(ss, SPI_SH_RBR); |
268 | } | 277 | } |
269 | 278 | ||
270 | remain -= cur_len; | 279 | remain -= cur_len; |
271 | data += cur_len; | 280 | data += cur_len; |
272 | } | 281 | } |
273 | 282 | ||
274 | /* deassert CS when SPI is receiving. */ | 283 | /* deassert CS when SPI is receiving. */ |
275 | if (t->len > SPI_SH_MAX_BYTE) { | 284 | if (t->len > SPI_SH_MAX_BYTE) { |
276 | clear_fifo(ss); | 285 | clear_fifo(ss); |
277 | spi_sh_write(ss, 1, SPI_SH_CR3); | 286 | spi_sh_write(ss, 1, SPI_SH_CR3); |
278 | } else { | 287 | } else { |
279 | spi_sh_write(ss, 0, SPI_SH_CR3); | 288 | spi_sh_write(ss, 0, SPI_SH_CR3); |
280 | } | 289 | } |
281 | 290 | ||
282 | return 0; | 291 | return 0; |
283 | } | 292 | } |
284 | 293 | ||
285 | static void spi_sh_work(struct work_struct *work) | 294 | static void spi_sh_work(struct work_struct *work) |
286 | { | 295 | { |
287 | struct spi_sh_data *ss = container_of(work, struct spi_sh_data, ws); | 296 | struct spi_sh_data *ss = container_of(work, struct spi_sh_data, ws); |
288 | struct spi_message *mesg; | 297 | struct spi_message *mesg; |
289 | struct spi_transfer *t; | 298 | struct spi_transfer *t; |
290 | unsigned long flags; | 299 | unsigned long flags; |
291 | int ret; | 300 | int ret; |
292 | 301 | ||
293 | pr_debug("%s: enter\n", __func__); | 302 | pr_debug("%s: enter\n", __func__); |
294 | 303 | ||
295 | spin_lock_irqsave(&ss->lock, flags); | 304 | spin_lock_irqsave(&ss->lock, flags); |
296 | while (!list_empty(&ss->queue)) { | 305 | while (!list_empty(&ss->queue)) { |
297 | mesg = list_entry(ss->queue.next, struct spi_message, queue); | 306 | mesg = list_entry(ss->queue.next, struct spi_message, queue); |
298 | list_del_init(&mesg->queue); | 307 | list_del_init(&mesg->queue); |
299 | 308 | ||
300 | spin_unlock_irqrestore(&ss->lock, flags); | 309 | spin_unlock_irqrestore(&ss->lock, flags); |
301 | list_for_each_entry(t, &mesg->transfers, transfer_list) { | 310 | list_for_each_entry(t, &mesg->transfers, transfer_list) { |
302 | pr_debug("tx_buf = %p, rx_buf = %p\n", | 311 | pr_debug("tx_buf = %p, rx_buf = %p\n", |
303 | t->tx_buf, t->rx_buf); | 312 | t->tx_buf, t->rx_buf); |
304 | pr_debug("len = %d, delay_usecs = %d\n", | 313 | pr_debug("len = %d, delay_usecs = %d\n", |
305 | t->len, t->delay_usecs); | 314 | t->len, t->delay_usecs); |
306 | 315 | ||
307 | if (t->tx_buf) { | 316 | if (t->tx_buf) { |
308 | ret = spi_sh_send(ss, mesg, t); | 317 | ret = spi_sh_send(ss, mesg, t); |
309 | if (ret < 0) | 318 | if (ret < 0) |
310 | goto error; | 319 | goto error; |
311 | } | 320 | } |
312 | if (t->rx_buf) { | 321 | if (t->rx_buf) { |
313 | ret = spi_sh_receive(ss, mesg, t); | 322 | ret = spi_sh_receive(ss, mesg, t); |
314 | if (ret < 0) | 323 | if (ret < 0) |
315 | goto error; | 324 | goto error; |
316 | } | 325 | } |
317 | mesg->actual_length += t->len; | 326 | mesg->actual_length += t->len; |
318 | } | 327 | } |
319 | spin_lock_irqsave(&ss->lock, flags); | 328 | spin_lock_irqsave(&ss->lock, flags); |
320 | 329 | ||
321 | mesg->status = 0; | 330 | mesg->status = 0; |
322 | mesg->complete(mesg->context); | 331 | mesg->complete(mesg->context); |
323 | } | 332 | } |
324 | 333 | ||
325 | clear_fifo(ss); | 334 | clear_fifo(ss); |
326 | spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1); | 335 | spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1); |
327 | udelay(100); | 336 | udelay(100); |
328 | 337 | ||
329 | spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, | 338 | spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, |
330 | SPI_SH_CR1); | 339 | SPI_SH_CR1); |
331 | 340 | ||
332 | clear_fifo(ss); | 341 | clear_fifo(ss); |
333 | 342 | ||
334 | spin_unlock_irqrestore(&ss->lock, flags); | 343 | spin_unlock_irqrestore(&ss->lock, flags); |
335 | 344 | ||
336 | return; | 345 | return; |
337 | 346 | ||
338 | error: | 347 | error: |
339 | mesg->status = ret; | 348 | mesg->status = ret; |
340 | mesg->complete(mesg->context); | 349 | mesg->complete(mesg->context); |
341 | 350 | ||
342 | spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, | 351 | spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, |
343 | SPI_SH_CR1); | 352 | SPI_SH_CR1); |
344 | clear_fifo(ss); | 353 | clear_fifo(ss); |
345 | 354 | ||
346 | } | 355 | } |
347 | 356 | ||
348 | static int spi_sh_setup(struct spi_device *spi) | 357 | static int spi_sh_setup(struct spi_device *spi) |
349 | { | 358 | { |
350 | struct spi_sh_data *ss = spi_master_get_devdata(spi->master); | 359 | struct spi_sh_data *ss = spi_master_get_devdata(spi->master); |
351 | 360 | ||
352 | if (!spi->bits_per_word) | 361 | if (!spi->bits_per_word) |
353 | spi->bits_per_word = 8; | 362 | spi->bits_per_word = 8; |
354 | 363 | ||
355 | pr_debug("%s: enter\n", __func__); | 364 | pr_debug("%s: enter\n", __func__); |
356 | 365 | ||
357 | spi_sh_write(ss, 0xfe, SPI_SH_CR1); /* SPI sycle stop */ | 366 | spi_sh_write(ss, 0xfe, SPI_SH_CR1); /* SPI sycle stop */ |
358 | spi_sh_write(ss, 0x00, SPI_SH_CR1); /* CR1 init */ | 367 | spi_sh_write(ss, 0x00, SPI_SH_CR1); /* CR1 init */ |
359 | spi_sh_write(ss, 0x00, SPI_SH_CR3); /* CR3 init */ | 368 | spi_sh_write(ss, 0x00, SPI_SH_CR3); /* CR3 init */ |
360 | 369 | ||
361 | clear_fifo(ss); | 370 | clear_fifo(ss); |
362 | 371 | ||
363 | /* 1/8 clock */ | 372 | /* 1/8 clock */ |
364 | spi_sh_write(ss, spi_sh_read(ss, SPI_SH_CR2) | 0x07, SPI_SH_CR2); | 373 | spi_sh_write(ss, spi_sh_read(ss, SPI_SH_CR2) | 0x07, SPI_SH_CR2); |
365 | udelay(10); | 374 | udelay(10); |
366 | 375 | ||
367 | return 0; | 376 | return 0; |
368 | } | 377 | } |
369 | 378 | ||
370 | static int spi_sh_transfer(struct spi_device *spi, struct spi_message *mesg) | 379 | static int spi_sh_transfer(struct spi_device *spi, struct spi_message *mesg) |
371 | { | 380 | { |
372 | struct spi_sh_data *ss = spi_master_get_devdata(spi->master); | 381 | struct spi_sh_data *ss = spi_master_get_devdata(spi->master); |
373 | unsigned long flags; | 382 | unsigned long flags; |
374 | 383 | ||
375 | pr_debug("%s: enter\n", __func__); | 384 | pr_debug("%s: enter\n", __func__); |
376 | pr_debug("\tmode = %02x\n", spi->mode); | 385 | pr_debug("\tmode = %02x\n", spi->mode); |
377 | 386 | ||
378 | spin_lock_irqsave(&ss->lock, flags); | 387 | spin_lock_irqsave(&ss->lock, flags); |
379 | 388 | ||
380 | mesg->actual_length = 0; | 389 | mesg->actual_length = 0; |
381 | mesg->status = -EINPROGRESS; | 390 | mesg->status = -EINPROGRESS; |
382 | 391 | ||
383 | spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1); | 392 | spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1); |
384 | 393 | ||
385 | list_add_tail(&mesg->queue, &ss->queue); | 394 | list_add_tail(&mesg->queue, &ss->queue); |
386 | queue_work(ss->workqueue, &ss->ws); | 395 | queue_work(ss->workqueue, &ss->ws); |
387 | 396 | ||
388 | spin_unlock_irqrestore(&ss->lock, flags); | 397 | spin_unlock_irqrestore(&ss->lock, flags); |
389 | 398 | ||
390 | return 0; | 399 | return 0; |
391 | } | 400 | } |
392 | 401 | ||
393 | static void spi_sh_cleanup(struct spi_device *spi) | 402 | static void spi_sh_cleanup(struct spi_device *spi) |
394 | { | 403 | { |
395 | struct spi_sh_data *ss = spi_master_get_devdata(spi->master); | 404 | struct spi_sh_data *ss = spi_master_get_devdata(spi->master); |
396 | 405 | ||
397 | pr_debug("%s: enter\n", __func__); | 406 | pr_debug("%s: enter\n", __func__); |
398 | 407 | ||
399 | spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, | 408 | spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, |
400 | SPI_SH_CR1); | 409 | SPI_SH_CR1); |
401 | } | 410 | } |
402 | 411 | ||
403 | static irqreturn_t spi_sh_irq(int irq, void *_ss) | 412 | static irqreturn_t spi_sh_irq(int irq, void *_ss) |
404 | { | 413 | { |
405 | struct spi_sh_data *ss = (struct spi_sh_data *)_ss; | 414 | struct spi_sh_data *ss = (struct spi_sh_data *)_ss; |
406 | unsigned long cr1; | 415 | unsigned long cr1; |
407 | 416 | ||
408 | cr1 = spi_sh_read(ss, SPI_SH_CR1); | 417 | cr1 = spi_sh_read(ss, SPI_SH_CR1); |
409 | if (cr1 & SPI_SH_TBE) | 418 | if (cr1 & SPI_SH_TBE) |
410 | ss->cr1 |= SPI_SH_TBE; | 419 | ss->cr1 |= SPI_SH_TBE; |
411 | if (cr1 & SPI_SH_TBF) | 420 | if (cr1 & SPI_SH_TBF) |
412 | ss->cr1 |= SPI_SH_TBF; | 421 | ss->cr1 |= SPI_SH_TBF; |
413 | if (cr1 & SPI_SH_RBE) | 422 | if (cr1 & SPI_SH_RBE) |
414 | ss->cr1 |= SPI_SH_RBE; | 423 | ss->cr1 |= SPI_SH_RBE; |
415 | if (cr1 & SPI_SH_RBF) | 424 | if (cr1 & SPI_SH_RBF) |
416 | ss->cr1 |= SPI_SH_RBF; | 425 | ss->cr1 |= SPI_SH_RBF; |
417 | 426 | ||
418 | if (ss->cr1) { | 427 | if (ss->cr1) { |
419 | spi_sh_clear_bit(ss, ss->cr1, SPI_SH_CR4); | 428 | spi_sh_clear_bit(ss, ss->cr1, SPI_SH_CR4); |
420 | wake_up(&ss->wait); | 429 | wake_up(&ss->wait); |
421 | } | 430 | } |
422 | 431 | ||
423 | return IRQ_HANDLED; | 432 | return IRQ_HANDLED; |
424 | } | 433 | } |
425 | 434 | ||
426 | static int __devexit spi_sh_remove(struct platform_device *pdev) | 435 | static int __devexit spi_sh_remove(struct platform_device *pdev) |
427 | { | 436 | { |
428 | struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev); | 437 | struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev); |
429 | 438 | ||
430 | spi_unregister_master(ss->master); | 439 | spi_unregister_master(ss->master); |
431 | destroy_workqueue(ss->workqueue); | 440 | destroy_workqueue(ss->workqueue); |
432 | free_irq(ss->irq, ss); | 441 | free_irq(ss->irq, ss); |
433 | iounmap(ss->addr); | 442 | iounmap(ss->addr); |
434 | 443 | ||
435 | return 0; | 444 | return 0; |
436 | } | 445 | } |
437 | 446 | ||
438 | static int __devinit spi_sh_probe(struct platform_device *pdev) | 447 | static int __devinit spi_sh_probe(struct platform_device *pdev) |
439 | { | 448 | { |
440 | struct resource *res; | 449 | struct resource *res; |
441 | struct spi_master *master; | 450 | struct spi_master *master; |
442 | struct spi_sh_data *ss; | 451 | struct spi_sh_data *ss; |
443 | int ret, irq; | 452 | int ret, irq; |
444 | 453 | ||
445 | /* get base addr */ | 454 | /* get base addr */ |
446 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 455 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
447 | if (unlikely(res == NULL)) { | 456 | if (unlikely(res == NULL)) { |
448 | dev_err(&pdev->dev, "invalid resource\n"); | 457 | dev_err(&pdev->dev, "invalid resource\n"); |
449 | return -EINVAL; | 458 | return -EINVAL; |
450 | } | 459 | } |
451 | 460 | ||
452 | irq = platform_get_irq(pdev, 0); | 461 | irq = platform_get_irq(pdev, 0); |
453 | if (irq < 0) { | 462 | if (irq < 0) { |
454 | dev_err(&pdev->dev, "platform_get_irq error\n"); | 463 | dev_err(&pdev->dev, "platform_get_irq error\n"); |
455 | return -ENODEV; | 464 | return -ENODEV; |
456 | } | 465 | } |
457 | 466 | ||
458 | master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); | 467 | master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); |
459 | if (master == NULL) { | 468 | if (master == NULL) { |
460 | dev_err(&pdev->dev, "spi_alloc_master error.\n"); | 469 | dev_err(&pdev->dev, "spi_alloc_master error.\n"); |
461 | return -ENOMEM; | 470 | return -ENOMEM; |
462 | } | 471 | } |
463 | 472 | ||
464 | ss = spi_master_get_devdata(master); | 473 | ss = spi_master_get_devdata(master); |
465 | dev_set_drvdata(&pdev->dev, ss); | 474 | dev_set_drvdata(&pdev->dev, ss); |
466 | 475 | ||
476 | switch (res->flags & IORESOURCE_MEM_TYPE_MASK) { | ||
477 | case IORESOURCE_MEM_8BIT: | ||
478 | ss->width = 8; | ||
479 | break; | ||
480 | case IORESOURCE_MEM_32BIT: | ||
481 | ss->width = 32; | ||
482 | break; | ||
483 | default: | ||
484 | dev_err(&pdev->dev, "No support width\n"); | ||
485 | ret = -ENODEV; | ||
486 | goto error1; | ||
487 | } | ||
467 | ss->irq = irq; | 488 | ss->irq = irq; |
468 | ss->master = master; | 489 | ss->master = master; |
469 | ss->addr = ioremap(res->start, resource_size(res)); | 490 | ss->addr = ioremap(res->start, resource_size(res)); |
470 | if (ss->addr == NULL) { | 491 | if (ss->addr == NULL) { |
471 | dev_err(&pdev->dev, "ioremap error.\n"); | 492 | dev_err(&pdev->dev, "ioremap error.\n"); |
472 | ret = -ENOMEM; | 493 | ret = -ENOMEM; |
473 | goto error1; | 494 | goto error1; |
474 | } | 495 | } |
475 | INIT_LIST_HEAD(&ss->queue); | 496 | INIT_LIST_HEAD(&ss->queue); |
476 | spin_lock_init(&ss->lock); | 497 | spin_lock_init(&ss->lock); |
477 | INIT_WORK(&ss->ws, spi_sh_work); | 498 | INIT_WORK(&ss->ws, spi_sh_work); |
478 | init_waitqueue_head(&ss->wait); | 499 | init_waitqueue_head(&ss->wait); |
479 | ss->workqueue = create_singlethread_workqueue( | 500 | ss->workqueue = create_singlethread_workqueue( |
480 | dev_name(master->dev.parent)); | 501 | dev_name(master->dev.parent)); |
481 | if (ss->workqueue == NULL) { | 502 | if (ss->workqueue == NULL) { |
482 | dev_err(&pdev->dev, "create workqueue error\n"); | 503 | dev_err(&pdev->dev, "create workqueue error\n"); |
483 | ret = -EBUSY; | 504 | ret = -EBUSY; |
484 | goto error2; | 505 | goto error2; |
485 | } | 506 | } |
486 | 507 | ||
487 | ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss); | 508 | ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss); |
488 | if (ret < 0) { | 509 | if (ret < 0) { |
489 | dev_err(&pdev->dev, "request_irq error\n"); | 510 | dev_err(&pdev->dev, "request_irq error\n"); |
490 | goto error3; | 511 | goto error3; |
491 | } | 512 | } |
492 | 513 | ||
493 | master->num_chipselect = 2; | 514 | master->num_chipselect = 2; |
494 | master->bus_num = pdev->id; | 515 | master->bus_num = pdev->id; |
495 | master->setup = spi_sh_setup; | 516 | master->setup = spi_sh_setup; |
496 | master->transfer = spi_sh_transfer; | 517 | master->transfer = spi_sh_transfer; |
497 | master->cleanup = spi_sh_cleanup; | 518 | master->cleanup = spi_sh_cleanup; |
498 | 519 | ||
499 | ret = spi_register_master(master); | 520 | ret = spi_register_master(master); |
500 | if (ret < 0) { | 521 | if (ret < 0) { |
501 | printk(KERN_ERR "spi_register_master error.\n"); | 522 | printk(KERN_ERR "spi_register_master error.\n"); |
502 | goto error4; | 523 | goto error4; |
503 | } | 524 | } |
504 | 525 | ||
505 | return 0; | 526 | return 0; |
506 | 527 | ||
507 | error4: | 528 | error4: |
508 | free_irq(irq, ss); | 529 | free_irq(irq, ss); |
509 | error3: | 530 | error3: |
510 | destroy_workqueue(ss->workqueue); | 531 | destroy_workqueue(ss->workqueue); |
511 | error2: | 532 | error2: |
512 | iounmap(ss->addr); | 533 | iounmap(ss->addr); |
513 | error1: | 534 | error1: |
514 | spi_master_put(master); | 535 | spi_master_put(master); |
515 | 536 | ||
516 | return ret; | 537 | return ret; |
517 | } | 538 | } |
518 | 539 | ||
519 | static struct platform_driver spi_sh_driver = { | 540 | static struct platform_driver spi_sh_driver = { |
520 | .probe = spi_sh_probe, | 541 | .probe = spi_sh_probe, |
521 | .remove = __devexit_p(spi_sh_remove), | 542 | .remove = __devexit_p(spi_sh_remove), |
522 | .driver = { | 543 | .driver = { |
523 | .name = "sh_spi", | 544 | .name = "sh_spi", |
524 | .owner = THIS_MODULE, | 545 | .owner = THIS_MODULE, |
525 | }, | 546 | }, |
526 | }; | 547 | }; |
527 | module_platform_driver(spi_sh_driver); | 548 | module_platform_driver(spi_sh_driver); |
528 | 549 | ||
529 | MODULE_DESCRIPTION("SH SPI bus driver"); | 550 | MODULE_DESCRIPTION("SH SPI bus driver"); |
530 | MODULE_LICENSE("GPL"); | 551 | MODULE_LICENSE("GPL"); |
531 | MODULE_AUTHOR("Yoshihiro Shimoda"); | 552 | MODULE_AUTHOR("Yoshihiro Shimoda"); |
532 | MODULE_ALIAS("platform:sh_spi"); | 553 | MODULE_ALIAS("platform:sh_spi"); |
533 | 554 |