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