19135bac3SWolfram Sang // SPDX-License-Identifier: GPL-2.0 2ca632f55SGrant Likely /* 3ca632f55SGrant Likely * SH SPI bus driver 4ca632f55SGrant Likely * 5ca632f55SGrant Likely * Copyright (C) 2011 Renesas Solutions Corp. 6ca632f55SGrant Likely * 7ca632f55SGrant Likely * Based on pxa2xx_spi.c: 8ca632f55SGrant Likely * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs 9ca632f55SGrant Likely */ 10ca632f55SGrant Likely 11ca632f55SGrant Likely #include <linux/module.h> 12ca632f55SGrant Likely #include <linux/kernel.h> 13ca632f55SGrant Likely #include <linux/sched.h> 14ca632f55SGrant Likely #include <linux/errno.h> 15ca632f55SGrant Likely #include <linux/timer.h> 16ca632f55SGrant Likely #include <linux/delay.h> 17ca632f55SGrant Likely #include <linux/list.h> 18ca632f55SGrant Likely #include <linux/workqueue.h> 19ca632f55SGrant Likely #include <linux/interrupt.h> 20ca632f55SGrant Likely #include <linux/platform_device.h> 21ca632f55SGrant Likely #include <linux/io.h> 22ca632f55SGrant Likely #include <linux/spi/spi.h> 23ca632f55SGrant Likely 24ca632f55SGrant Likely #define SPI_SH_TBR 0x00 25ca632f55SGrant Likely #define SPI_SH_RBR 0x00 26ca632f55SGrant Likely #define SPI_SH_CR1 0x08 27ca632f55SGrant Likely #define SPI_SH_CR2 0x10 28ca632f55SGrant Likely #define SPI_SH_CR3 0x18 29ca632f55SGrant Likely #define SPI_SH_CR4 0x20 30ca632f55SGrant Likely #define SPI_SH_CR5 0x28 31ca632f55SGrant Likely 32ca632f55SGrant Likely /* CR1 */ 33ca632f55SGrant Likely #define SPI_SH_TBE 0x80 34ca632f55SGrant Likely #define SPI_SH_TBF 0x40 35ca632f55SGrant Likely #define SPI_SH_RBE 0x20 36ca632f55SGrant Likely #define SPI_SH_RBF 0x10 37ca632f55SGrant Likely #define SPI_SH_PFONRD 0x08 38ca632f55SGrant Likely #define SPI_SH_SSDB 0x04 39ca632f55SGrant Likely #define SPI_SH_SSD 0x02 40ca632f55SGrant Likely #define SPI_SH_SSA 0x01 41ca632f55SGrant Likely 42ca632f55SGrant Likely /* CR2 */ 43ca632f55SGrant Likely #define SPI_SH_RSTF 0x80 44ca632f55SGrant Likely #define SPI_SH_LOOPBK 0x40 45ca632f55SGrant Likely #define SPI_SH_CPOL 0x20 46ca632f55SGrant Likely #define SPI_SH_CPHA 0x10 47ca632f55SGrant Likely #define SPI_SH_L1M0 0x08 48ca632f55SGrant Likely 49ca632f55SGrant Likely /* CR3 */ 50ca632f55SGrant Likely #define SPI_SH_MAX_BYTE 0xFF 51ca632f55SGrant Likely 52ca632f55SGrant Likely /* CR4 */ 53ca632f55SGrant Likely #define SPI_SH_TBEI 0x80 54ca632f55SGrant Likely #define SPI_SH_TBFI 0x40 55ca632f55SGrant Likely #define SPI_SH_RBEI 0x20 56ca632f55SGrant Likely #define SPI_SH_RBFI 0x10 57ca632f55SGrant Likely #define SPI_SH_WPABRT 0x04 58ca632f55SGrant Likely #define SPI_SH_SSS 0x01 59ca632f55SGrant Likely 60ca632f55SGrant Likely /* CR8 */ 61ca632f55SGrant Likely #define SPI_SH_P1L0 0x80 62ca632f55SGrant Likely #define SPI_SH_PP1L0 0x40 63ca632f55SGrant Likely #define SPI_SH_MUXI 0x20 64ca632f55SGrant Likely #define SPI_SH_MUXIRQ 0x10 65ca632f55SGrant Likely 66ca632f55SGrant Likely #define SPI_SH_FIFO_SIZE 32 67ca632f55SGrant Likely #define SPI_SH_SEND_TIMEOUT (3 * HZ) 68ca632f55SGrant Likely #define SPI_SH_RECEIVE_TIMEOUT (HZ >> 3) 69ca632f55SGrant Likely 70ca632f55SGrant Likely #undef DEBUG 71ca632f55SGrant Likely 72ca632f55SGrant Likely struct spi_sh_data { 73ca632f55SGrant Likely void __iomem *addr; 74ca632f55SGrant Likely int irq; 75ca632f55SGrant Likely struct spi_master *master; 76ca632f55SGrant Likely struct list_head queue; 77ca632f55SGrant Likely struct work_struct ws; 78ca632f55SGrant Likely unsigned long cr1; 79ca632f55SGrant Likely wait_queue_head_t wait; 80ca632f55SGrant Likely spinlock_t lock; 810eb8880fSShimoda, Yoshihiro int width; 82ca632f55SGrant Likely }; 83ca632f55SGrant Likely 84ca632f55SGrant Likely static void spi_sh_write(struct spi_sh_data *ss, unsigned long data, 85ca632f55SGrant Likely unsigned long offset) 86ca632f55SGrant Likely { 870eb8880fSShimoda, Yoshihiro if (ss->width == 8) 880eb8880fSShimoda, Yoshihiro iowrite8(data, ss->addr + (offset >> 2)); 890eb8880fSShimoda, Yoshihiro else if (ss->width == 32) 900eb8880fSShimoda, Yoshihiro iowrite32(data, ss->addr + offset); 91ca632f55SGrant Likely } 92ca632f55SGrant Likely 93ca632f55SGrant Likely static unsigned long spi_sh_read(struct spi_sh_data *ss, unsigned long offset) 94ca632f55SGrant Likely { 950eb8880fSShimoda, Yoshihiro if (ss->width == 8) 960eb8880fSShimoda, Yoshihiro return ioread8(ss->addr + (offset >> 2)); 970eb8880fSShimoda, Yoshihiro else if (ss->width == 32) 980eb8880fSShimoda, Yoshihiro return ioread32(ss->addr + offset); 990eb8880fSShimoda, Yoshihiro else 1000eb8880fSShimoda, Yoshihiro return 0; 101ca632f55SGrant Likely } 102ca632f55SGrant Likely 103ca632f55SGrant Likely static void spi_sh_set_bit(struct spi_sh_data *ss, unsigned long val, 104ca632f55SGrant Likely unsigned long offset) 105ca632f55SGrant Likely { 106ca632f55SGrant Likely unsigned long tmp; 107ca632f55SGrant Likely 108ca632f55SGrant Likely tmp = spi_sh_read(ss, offset); 109ca632f55SGrant Likely tmp |= val; 110ca632f55SGrant Likely spi_sh_write(ss, tmp, offset); 111ca632f55SGrant Likely } 112ca632f55SGrant Likely 113ca632f55SGrant Likely static void spi_sh_clear_bit(struct spi_sh_data *ss, unsigned long val, 114ca632f55SGrant Likely unsigned long offset) 115ca632f55SGrant Likely { 116ca632f55SGrant Likely unsigned long tmp; 117ca632f55SGrant Likely 118ca632f55SGrant Likely tmp = spi_sh_read(ss, offset); 119ca632f55SGrant Likely tmp &= ~val; 120ca632f55SGrant Likely spi_sh_write(ss, tmp, offset); 121ca632f55SGrant Likely } 122ca632f55SGrant Likely 123ca632f55SGrant Likely static void clear_fifo(struct spi_sh_data *ss) 124ca632f55SGrant Likely { 125ca632f55SGrant Likely spi_sh_set_bit(ss, SPI_SH_RSTF, SPI_SH_CR2); 126ca632f55SGrant Likely spi_sh_clear_bit(ss, SPI_SH_RSTF, SPI_SH_CR2); 127ca632f55SGrant Likely } 128ca632f55SGrant Likely 129ca632f55SGrant Likely static int spi_sh_wait_receive_buffer(struct spi_sh_data *ss) 130ca632f55SGrant Likely { 131ca632f55SGrant Likely int timeout = 100000; 132ca632f55SGrant Likely 133ca632f55SGrant Likely while (spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) { 134ca632f55SGrant Likely udelay(10); 135ca632f55SGrant Likely if (timeout-- < 0) 136ca632f55SGrant Likely return -ETIMEDOUT; 137ca632f55SGrant Likely } 138ca632f55SGrant Likely return 0; 139ca632f55SGrant Likely } 140ca632f55SGrant Likely 141ca632f55SGrant Likely static int spi_sh_wait_write_buffer_empty(struct spi_sh_data *ss) 142ca632f55SGrant Likely { 143ca632f55SGrant Likely int timeout = 100000; 144ca632f55SGrant Likely 145ca632f55SGrant Likely while (!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBE)) { 146ca632f55SGrant Likely udelay(10); 147ca632f55SGrant Likely if (timeout-- < 0) 148ca632f55SGrant Likely return -ETIMEDOUT; 149ca632f55SGrant Likely } 150ca632f55SGrant Likely return 0; 151ca632f55SGrant Likely } 152ca632f55SGrant Likely 153ca632f55SGrant Likely static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg, 154ca632f55SGrant Likely struct spi_transfer *t) 155ca632f55SGrant Likely { 156ca632f55SGrant Likely int i, retval = 0; 157ca632f55SGrant Likely int remain = t->len; 158ca632f55SGrant Likely int cur_len; 159ca632f55SGrant Likely unsigned char *data; 160ca632f55SGrant Likely long ret; 161ca632f55SGrant Likely 162ca632f55SGrant Likely if (t->len) 163ca632f55SGrant Likely spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); 164ca632f55SGrant Likely 165ca632f55SGrant Likely data = (unsigned char *)t->tx_buf; 166ca632f55SGrant Likely while (remain > 0) { 167ca632f55SGrant Likely cur_len = min(SPI_SH_FIFO_SIZE, remain); 168ca632f55SGrant Likely for (i = 0; i < cur_len && 169ca632f55SGrant Likely !(spi_sh_read(ss, SPI_SH_CR4) & 170ca632f55SGrant Likely SPI_SH_WPABRT) && 171ca632f55SGrant Likely !(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBF); 172ca632f55SGrant Likely i++) 173ca632f55SGrant Likely spi_sh_write(ss, (unsigned long)data[i], SPI_SH_TBR); 174ca632f55SGrant Likely 175ca632f55SGrant Likely if (spi_sh_read(ss, SPI_SH_CR4) & SPI_SH_WPABRT) { 176ca632f55SGrant Likely /* Abort SPI operation */ 177ca632f55SGrant Likely spi_sh_set_bit(ss, SPI_SH_WPABRT, SPI_SH_CR4); 178ca632f55SGrant Likely retval = -EIO; 179ca632f55SGrant Likely break; 180ca632f55SGrant Likely } 181ca632f55SGrant Likely 182ca632f55SGrant Likely cur_len = i; 183ca632f55SGrant Likely 184ca632f55SGrant Likely remain -= cur_len; 185ca632f55SGrant Likely data += cur_len; 186ca632f55SGrant Likely 187ca632f55SGrant Likely if (remain > 0) { 188ca632f55SGrant Likely ss->cr1 &= ~SPI_SH_TBE; 189ca632f55SGrant Likely spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4); 190ca632f55SGrant Likely ret = wait_event_interruptible_timeout(ss->wait, 191ca632f55SGrant Likely ss->cr1 & SPI_SH_TBE, 192ca632f55SGrant Likely SPI_SH_SEND_TIMEOUT); 193ca632f55SGrant Likely if (ret == 0 && !(ss->cr1 & SPI_SH_TBE)) { 194ca632f55SGrant Likely printk(KERN_ERR "%s: timeout\n", __func__); 195ca632f55SGrant Likely return -ETIMEDOUT; 196ca632f55SGrant Likely } 197ca632f55SGrant Likely } 198ca632f55SGrant Likely } 199ca632f55SGrant Likely 200ca632f55SGrant Likely if (list_is_last(&t->transfer_list, &mesg->transfers)) { 201909e709cSAxel Lin spi_sh_clear_bit(ss, SPI_SH_SSD | SPI_SH_SSDB, SPI_SH_CR1); 202ca632f55SGrant Likely spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); 203ca632f55SGrant Likely 204ca632f55SGrant Likely ss->cr1 &= ~SPI_SH_TBE; 205ca632f55SGrant Likely spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4); 206ca632f55SGrant Likely ret = wait_event_interruptible_timeout(ss->wait, 207ca632f55SGrant Likely ss->cr1 & SPI_SH_TBE, 208ca632f55SGrant Likely SPI_SH_SEND_TIMEOUT); 209ca632f55SGrant Likely if (ret == 0 && (ss->cr1 & SPI_SH_TBE)) { 210ca632f55SGrant Likely printk(KERN_ERR "%s: timeout\n", __func__); 211ca632f55SGrant Likely return -ETIMEDOUT; 212ca632f55SGrant Likely } 213ca632f55SGrant Likely } 214ca632f55SGrant Likely 215ca632f55SGrant Likely return retval; 216ca632f55SGrant Likely } 217ca632f55SGrant Likely 218ca632f55SGrant Likely static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg, 219ca632f55SGrant Likely struct spi_transfer *t) 220ca632f55SGrant Likely { 221ca632f55SGrant Likely int i; 222ca632f55SGrant Likely int remain = t->len; 223ca632f55SGrant Likely int cur_len; 224ca632f55SGrant Likely unsigned char *data; 225ca632f55SGrant Likely long ret; 226ca632f55SGrant Likely 227ca632f55SGrant Likely if (t->len > SPI_SH_MAX_BYTE) 228ca632f55SGrant Likely spi_sh_write(ss, SPI_SH_MAX_BYTE, SPI_SH_CR3); 229ca632f55SGrant Likely else 230ca632f55SGrant Likely spi_sh_write(ss, t->len, SPI_SH_CR3); 231ca632f55SGrant Likely 232909e709cSAxel Lin spi_sh_clear_bit(ss, SPI_SH_SSD | SPI_SH_SSDB, SPI_SH_CR1); 233ca632f55SGrant Likely spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); 234ca632f55SGrant Likely 235ca632f55SGrant Likely spi_sh_wait_write_buffer_empty(ss); 236ca632f55SGrant Likely 237ca632f55SGrant Likely data = (unsigned char *)t->rx_buf; 238ca632f55SGrant Likely while (remain > 0) { 239ca632f55SGrant Likely if (remain >= SPI_SH_FIFO_SIZE) { 240ca632f55SGrant Likely ss->cr1 &= ~SPI_SH_RBF; 241ca632f55SGrant Likely spi_sh_set_bit(ss, SPI_SH_RBF, SPI_SH_CR4); 242ca632f55SGrant Likely ret = wait_event_interruptible_timeout(ss->wait, 243ca632f55SGrant Likely ss->cr1 & SPI_SH_RBF, 244ca632f55SGrant Likely SPI_SH_RECEIVE_TIMEOUT); 245ca632f55SGrant Likely if (ret == 0 && 246ca632f55SGrant Likely spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) { 247ca632f55SGrant Likely printk(KERN_ERR "%s: timeout\n", __func__); 248ca632f55SGrant Likely return -ETIMEDOUT; 249ca632f55SGrant Likely } 250ca632f55SGrant Likely } 251ca632f55SGrant Likely 252ca632f55SGrant Likely cur_len = min(SPI_SH_FIFO_SIZE, remain); 253ca632f55SGrant Likely for (i = 0; i < cur_len; i++) { 254ca632f55SGrant Likely if (spi_sh_wait_receive_buffer(ss)) 255ca632f55SGrant Likely break; 256ca632f55SGrant Likely data[i] = (unsigned char)spi_sh_read(ss, SPI_SH_RBR); 257ca632f55SGrant Likely } 258ca632f55SGrant Likely 259ca632f55SGrant Likely remain -= cur_len; 260ca632f55SGrant Likely data += cur_len; 261ca632f55SGrant Likely } 262ca632f55SGrant Likely 263ca632f55SGrant Likely /* deassert CS when SPI is receiving. */ 264ca632f55SGrant Likely if (t->len > SPI_SH_MAX_BYTE) { 265ca632f55SGrant Likely clear_fifo(ss); 266ca632f55SGrant Likely spi_sh_write(ss, 1, SPI_SH_CR3); 267ca632f55SGrant Likely } else { 268ca632f55SGrant Likely spi_sh_write(ss, 0, SPI_SH_CR3); 269ca632f55SGrant Likely } 270ca632f55SGrant Likely 271ca632f55SGrant Likely return 0; 272ca632f55SGrant Likely } 273ca632f55SGrant Likely 274ca632f55SGrant Likely static void spi_sh_work(struct work_struct *work) 275ca632f55SGrant Likely { 276ca632f55SGrant Likely struct spi_sh_data *ss = container_of(work, struct spi_sh_data, ws); 277ca632f55SGrant Likely struct spi_message *mesg; 278ca632f55SGrant Likely struct spi_transfer *t; 279ca632f55SGrant Likely unsigned long flags; 280ca632f55SGrant Likely int ret; 281ca632f55SGrant Likely 282ca632f55SGrant Likely pr_debug("%s: enter\n", __func__); 283ca632f55SGrant Likely 284ca632f55SGrant Likely spin_lock_irqsave(&ss->lock, flags); 285ca632f55SGrant Likely while (!list_empty(&ss->queue)) { 286ca632f55SGrant Likely mesg = list_entry(ss->queue.next, struct spi_message, queue); 287ca632f55SGrant Likely list_del_init(&mesg->queue); 288ca632f55SGrant Likely 289ca632f55SGrant Likely spin_unlock_irqrestore(&ss->lock, flags); 290ca632f55SGrant Likely list_for_each_entry(t, &mesg->transfers, transfer_list) { 291ca632f55SGrant Likely pr_debug("tx_buf = %p, rx_buf = %p\n", 292ca632f55SGrant Likely t->tx_buf, t->rx_buf); 293ca632f55SGrant Likely pr_debug("len = %d, delay_usecs = %d\n", 294ca632f55SGrant Likely t->len, t->delay_usecs); 295ca632f55SGrant Likely 296ca632f55SGrant Likely if (t->tx_buf) { 297ca632f55SGrant Likely ret = spi_sh_send(ss, mesg, t); 298ca632f55SGrant Likely if (ret < 0) 299ca632f55SGrant Likely goto error; 300ca632f55SGrant Likely } 301ca632f55SGrant Likely if (t->rx_buf) { 302ca632f55SGrant Likely ret = spi_sh_receive(ss, mesg, t); 303ca632f55SGrant Likely if (ret < 0) 304ca632f55SGrant Likely goto error; 305ca632f55SGrant Likely } 306ca632f55SGrant Likely mesg->actual_length += t->len; 307ca632f55SGrant Likely } 308ca632f55SGrant Likely spin_lock_irqsave(&ss->lock, flags); 309ca632f55SGrant Likely 310ca632f55SGrant Likely mesg->status = 0; 3110a6d3879SAxel Lin if (mesg->complete) 312ca632f55SGrant Likely mesg->complete(mesg->context); 313ca632f55SGrant Likely } 314ca632f55SGrant Likely 315ca632f55SGrant Likely clear_fifo(ss); 316ca632f55SGrant Likely spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1); 317ca632f55SGrant Likely udelay(100); 318ca632f55SGrant Likely 319ca632f55SGrant Likely spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, 320ca632f55SGrant Likely SPI_SH_CR1); 321ca632f55SGrant Likely 322ca632f55SGrant Likely clear_fifo(ss); 323ca632f55SGrant Likely 324ca632f55SGrant Likely spin_unlock_irqrestore(&ss->lock, flags); 325ca632f55SGrant Likely 326ca632f55SGrant Likely return; 327ca632f55SGrant Likely 328ca632f55SGrant Likely error: 329ca632f55SGrant Likely mesg->status = ret; 3300a6d3879SAxel Lin if (mesg->complete) 331ca632f55SGrant Likely mesg->complete(mesg->context); 332ca632f55SGrant Likely 333ca632f55SGrant Likely spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, 334ca632f55SGrant Likely SPI_SH_CR1); 335ca632f55SGrant Likely clear_fifo(ss); 336ca632f55SGrant Likely 337ca632f55SGrant Likely } 338ca632f55SGrant Likely 339ca632f55SGrant Likely static int spi_sh_setup(struct spi_device *spi) 340ca632f55SGrant Likely { 341ca632f55SGrant Likely struct spi_sh_data *ss = spi_master_get_devdata(spi->master); 342ca632f55SGrant Likely 343ca632f55SGrant Likely pr_debug("%s: enter\n", __func__); 344ca632f55SGrant Likely 345ca632f55SGrant Likely spi_sh_write(ss, 0xfe, SPI_SH_CR1); /* SPI sycle stop */ 346ca632f55SGrant Likely spi_sh_write(ss, 0x00, SPI_SH_CR1); /* CR1 init */ 347ca632f55SGrant Likely spi_sh_write(ss, 0x00, SPI_SH_CR3); /* CR3 init */ 348ca632f55SGrant Likely 349ca632f55SGrant Likely clear_fifo(ss); 350ca632f55SGrant Likely 351ca632f55SGrant Likely /* 1/8 clock */ 352ca632f55SGrant Likely spi_sh_write(ss, spi_sh_read(ss, SPI_SH_CR2) | 0x07, SPI_SH_CR2); 353ca632f55SGrant Likely udelay(10); 354ca632f55SGrant Likely 355ca632f55SGrant Likely return 0; 356ca632f55SGrant Likely } 357ca632f55SGrant Likely 358ca632f55SGrant Likely static int spi_sh_transfer(struct spi_device *spi, struct spi_message *mesg) 359ca632f55SGrant Likely { 360ca632f55SGrant Likely struct spi_sh_data *ss = spi_master_get_devdata(spi->master); 361ca632f55SGrant Likely unsigned long flags; 362ca632f55SGrant Likely 363ca632f55SGrant Likely pr_debug("%s: enter\n", __func__); 364ca632f55SGrant Likely pr_debug("\tmode = %02x\n", spi->mode); 365ca632f55SGrant Likely 366ca632f55SGrant Likely spin_lock_irqsave(&ss->lock, flags); 367ca632f55SGrant Likely 368ca632f55SGrant Likely mesg->actual_length = 0; 369ca632f55SGrant Likely mesg->status = -EINPROGRESS; 370ca632f55SGrant Likely 371ca632f55SGrant Likely spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1); 372ca632f55SGrant Likely 373ca632f55SGrant Likely list_add_tail(&mesg->queue, &ss->queue); 37438e09920SBhaktipriya Shridhar schedule_work(&ss->ws); 375ca632f55SGrant Likely 376ca632f55SGrant Likely spin_unlock_irqrestore(&ss->lock, flags); 377ca632f55SGrant Likely 378ca632f55SGrant Likely return 0; 379ca632f55SGrant Likely } 380ca632f55SGrant Likely 381ca632f55SGrant Likely static void spi_sh_cleanup(struct spi_device *spi) 382ca632f55SGrant Likely { 383ca632f55SGrant Likely struct spi_sh_data *ss = spi_master_get_devdata(spi->master); 384ca632f55SGrant Likely 385ca632f55SGrant Likely pr_debug("%s: enter\n", __func__); 386ca632f55SGrant Likely 387ca632f55SGrant Likely spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, 388ca632f55SGrant Likely SPI_SH_CR1); 389ca632f55SGrant Likely } 390ca632f55SGrant Likely 391ca632f55SGrant Likely static irqreturn_t spi_sh_irq(int irq, void *_ss) 392ca632f55SGrant Likely { 393ca632f55SGrant Likely struct spi_sh_data *ss = (struct spi_sh_data *)_ss; 394ca632f55SGrant Likely unsigned long cr1; 395ca632f55SGrant Likely 396ca632f55SGrant Likely cr1 = spi_sh_read(ss, SPI_SH_CR1); 397ca632f55SGrant Likely if (cr1 & SPI_SH_TBE) 398ca632f55SGrant Likely ss->cr1 |= SPI_SH_TBE; 399ca632f55SGrant Likely if (cr1 & SPI_SH_TBF) 400ca632f55SGrant Likely ss->cr1 |= SPI_SH_TBF; 401ca632f55SGrant Likely if (cr1 & SPI_SH_RBE) 402ca632f55SGrant Likely ss->cr1 |= SPI_SH_RBE; 403ca632f55SGrant Likely if (cr1 & SPI_SH_RBF) 404ca632f55SGrant Likely ss->cr1 |= SPI_SH_RBF; 405ca632f55SGrant Likely 406ca632f55SGrant Likely if (ss->cr1) { 407ca632f55SGrant Likely spi_sh_clear_bit(ss, ss->cr1, SPI_SH_CR4); 408ca632f55SGrant Likely wake_up(&ss->wait); 409ca632f55SGrant Likely } 410ca632f55SGrant Likely 411ca632f55SGrant Likely return IRQ_HANDLED; 412ca632f55SGrant Likely } 413ca632f55SGrant Likely 414fd4a319bSGrant Likely static int spi_sh_remove(struct platform_device *pdev) 415ca632f55SGrant Likely { 41624b5a82cSJingoo Han struct spi_sh_data *ss = platform_get_drvdata(pdev); 417ca632f55SGrant Likely 418ca632f55SGrant Likely spi_unregister_master(ss->master); 41938e09920SBhaktipriya Shridhar flush_work(&ss->ws); 420ca632f55SGrant Likely free_irq(ss->irq, ss); 421ca632f55SGrant Likely 422ca632f55SGrant Likely return 0; 423ca632f55SGrant Likely } 424ca632f55SGrant Likely 425fd4a319bSGrant Likely static int spi_sh_probe(struct platform_device *pdev) 426ca632f55SGrant Likely { 427ca632f55SGrant Likely struct resource *res; 428ca632f55SGrant Likely struct spi_master *master; 429ca632f55SGrant Likely struct spi_sh_data *ss; 430ca632f55SGrant Likely int ret, irq; 431ca632f55SGrant Likely 432ca632f55SGrant Likely /* get base addr */ 433ca632f55SGrant Likely res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 434ca632f55SGrant Likely if (unlikely(res == NULL)) { 435ca632f55SGrant Likely dev_err(&pdev->dev, "invalid resource\n"); 436ca632f55SGrant Likely return -EINVAL; 437ca632f55SGrant Likely } 438ca632f55SGrant Likely 439ca632f55SGrant Likely irq = platform_get_irq(pdev, 0); 4406b8ac10eSStephen Boyd if (irq < 0) 441345fef75SGustavo A. R. Silva return irq; 442ca632f55SGrant Likely 443ca632f55SGrant Likely master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); 444ca632f55SGrant Likely if (master == NULL) { 445ca632f55SGrant Likely dev_err(&pdev->dev, "spi_alloc_master error.\n"); 446ca632f55SGrant Likely return -ENOMEM; 447ca632f55SGrant Likely } 448ca632f55SGrant Likely 449ca632f55SGrant Likely ss = spi_master_get_devdata(master); 45024b5a82cSJingoo Han platform_set_drvdata(pdev, ss); 451ca632f55SGrant Likely 4520eb8880fSShimoda, Yoshihiro switch (res->flags & IORESOURCE_MEM_TYPE_MASK) { 4530eb8880fSShimoda, Yoshihiro case IORESOURCE_MEM_8BIT: 4540eb8880fSShimoda, Yoshihiro ss->width = 8; 4550eb8880fSShimoda, Yoshihiro break; 4560eb8880fSShimoda, Yoshihiro case IORESOURCE_MEM_32BIT: 4570eb8880fSShimoda, Yoshihiro ss->width = 32; 4580eb8880fSShimoda, Yoshihiro break; 4590eb8880fSShimoda, Yoshihiro default: 4600eb8880fSShimoda, Yoshihiro dev_err(&pdev->dev, "No support width\n"); 4610eb8880fSShimoda, Yoshihiro ret = -ENODEV; 4620eb8880fSShimoda, Yoshihiro goto error1; 4630eb8880fSShimoda, Yoshihiro } 464ca632f55SGrant Likely ss->irq = irq; 465ca632f55SGrant Likely ss->master = master; 466e9d42d15SHimangi Saraogi ss->addr = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 467ca632f55SGrant Likely if (ss->addr == NULL) { 468ca632f55SGrant Likely dev_err(&pdev->dev, "ioremap error.\n"); 469ca632f55SGrant Likely ret = -ENOMEM; 470ca632f55SGrant Likely goto error1; 471ca632f55SGrant Likely } 472ca632f55SGrant Likely INIT_LIST_HEAD(&ss->queue); 473ca632f55SGrant Likely spin_lock_init(&ss->lock); 474ca632f55SGrant Likely INIT_WORK(&ss->ws, spi_sh_work); 475ca632f55SGrant Likely init_waitqueue_head(&ss->wait); 476ca632f55SGrant Likely 47738ada214SYong Zhang ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss); 478ca632f55SGrant Likely if (ret < 0) { 479ca632f55SGrant Likely dev_err(&pdev->dev, "request_irq error\n"); 48038e09920SBhaktipriya Shridhar goto error1; 481ca632f55SGrant Likely } 482ca632f55SGrant Likely 483ca632f55SGrant Likely master->num_chipselect = 2; 484ca632f55SGrant Likely master->bus_num = pdev->id; 485ca632f55SGrant Likely master->setup = spi_sh_setup; 486ca632f55SGrant Likely master->transfer = spi_sh_transfer; 487ca632f55SGrant Likely master->cleanup = spi_sh_cleanup; 488ca632f55SGrant Likely 489ca632f55SGrant Likely ret = spi_register_master(master); 490ca632f55SGrant Likely if (ret < 0) { 491ca632f55SGrant Likely printk(KERN_ERR "spi_register_master error.\n"); 492e9d42d15SHimangi Saraogi goto error3; 493ca632f55SGrant Likely } 494ca632f55SGrant Likely 495ca632f55SGrant Likely return 0; 496ca632f55SGrant Likely 497ca632f55SGrant Likely error3: 498e9d42d15SHimangi Saraogi free_irq(irq, ss); 499ca632f55SGrant Likely error1: 500ca632f55SGrant Likely spi_master_put(master); 501ca632f55SGrant Likely 502ca632f55SGrant Likely return ret; 503ca632f55SGrant Likely } 504ca632f55SGrant Likely 505ca632f55SGrant Likely static struct platform_driver spi_sh_driver = { 506ca632f55SGrant Likely .probe = spi_sh_probe, 507fd4a319bSGrant Likely .remove = spi_sh_remove, 508ca632f55SGrant Likely .driver = { 509ca632f55SGrant Likely .name = "sh_spi", 510ca632f55SGrant Likely }, 511ca632f55SGrant Likely }; 512940ab889SGrant Likely module_platform_driver(spi_sh_driver); 513ca632f55SGrant Likely 514ca632f55SGrant Likely MODULE_DESCRIPTION("SH SPI bus driver"); 5159135bac3SWolfram Sang MODULE_LICENSE("GPL v2"); 516ca632f55SGrant Likely MODULE_AUTHOR("Yoshihiro Shimoda"); 517ca632f55SGrant Likely MODULE_ALIAS("platform:sh_spi"); 518