diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/drivers/spi/spi-sh.c | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/drivers/spi/spi-sh.c')
-rw-r--r-- | ANDROID_3.4.5/drivers/spi/spi-sh.c | 553 |
1 files changed, 0 insertions, 553 deletions
diff --git a/ANDROID_3.4.5/drivers/spi/spi-sh.c b/ANDROID_3.4.5/drivers/spi/spi-sh.c deleted file mode 100644 index 79442c31..00000000 --- a/ANDROID_3.4.5/drivers/spi/spi-sh.c +++ /dev/null @@ -1,553 +0,0 @@ -/* - * SH SPI bus driver - * - * Copyright (C) 2011 Renesas Solutions Corp. - * - * Based on pxa2xx_spi.c: - * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/timer.h> -#include <linux/delay.h> -#include <linux/list.h> -#include <linux/workqueue.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/spi/spi.h> - -#define SPI_SH_TBR 0x00 -#define SPI_SH_RBR 0x00 -#define SPI_SH_CR1 0x08 -#define SPI_SH_CR2 0x10 -#define SPI_SH_CR3 0x18 -#define SPI_SH_CR4 0x20 -#define SPI_SH_CR5 0x28 - -/* CR1 */ -#define SPI_SH_TBE 0x80 -#define SPI_SH_TBF 0x40 -#define SPI_SH_RBE 0x20 -#define SPI_SH_RBF 0x10 -#define SPI_SH_PFONRD 0x08 -#define SPI_SH_SSDB 0x04 -#define SPI_SH_SSD 0x02 -#define SPI_SH_SSA 0x01 - -/* CR2 */ -#define SPI_SH_RSTF 0x80 -#define SPI_SH_LOOPBK 0x40 -#define SPI_SH_CPOL 0x20 -#define SPI_SH_CPHA 0x10 -#define SPI_SH_L1M0 0x08 - -/* CR3 */ -#define SPI_SH_MAX_BYTE 0xFF - -/* CR4 */ -#define SPI_SH_TBEI 0x80 -#define SPI_SH_TBFI 0x40 -#define SPI_SH_RBEI 0x20 -#define SPI_SH_RBFI 0x10 -#define SPI_SH_WPABRT 0x04 -#define SPI_SH_SSS 0x01 - -/* CR8 */ -#define SPI_SH_P1L0 0x80 -#define SPI_SH_PP1L0 0x40 -#define SPI_SH_MUXI 0x20 -#define SPI_SH_MUXIRQ 0x10 - -#define SPI_SH_FIFO_SIZE 32 -#define SPI_SH_SEND_TIMEOUT (3 * HZ) -#define SPI_SH_RECEIVE_TIMEOUT (HZ >> 3) - -#undef DEBUG - -struct spi_sh_data { - void __iomem *addr; - int irq; - struct spi_master *master; - struct list_head queue; - struct workqueue_struct *workqueue; - struct work_struct ws; - unsigned long cr1; - wait_queue_head_t wait; - spinlock_t lock; - int width; -}; - -static void spi_sh_write(struct spi_sh_data *ss, unsigned long data, - unsigned long offset) -{ - if (ss->width == 8) - iowrite8(data, ss->addr + (offset >> 2)); - else if (ss->width == 32) - iowrite32(data, ss->addr + offset); -} - -static unsigned long spi_sh_read(struct spi_sh_data *ss, unsigned long offset) -{ - if (ss->width == 8) - return ioread8(ss->addr + (offset >> 2)); - else if (ss->width == 32) - return ioread32(ss->addr + offset); - else - return 0; -} - -static void spi_sh_set_bit(struct spi_sh_data *ss, unsigned long val, - unsigned long offset) -{ - unsigned long tmp; - - tmp = spi_sh_read(ss, offset); - tmp |= val; - spi_sh_write(ss, tmp, offset); -} - -static void spi_sh_clear_bit(struct spi_sh_data *ss, unsigned long val, - unsigned long offset) -{ - unsigned long tmp; - - tmp = spi_sh_read(ss, offset); - tmp &= ~val; - spi_sh_write(ss, tmp, offset); -} - -static void clear_fifo(struct spi_sh_data *ss) -{ - spi_sh_set_bit(ss, SPI_SH_RSTF, SPI_SH_CR2); - spi_sh_clear_bit(ss, SPI_SH_RSTF, SPI_SH_CR2); -} - -static int spi_sh_wait_receive_buffer(struct spi_sh_data *ss) -{ - int timeout = 100000; - - while (spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) { - udelay(10); - if (timeout-- < 0) - return -ETIMEDOUT; - } - return 0; -} - -static int spi_sh_wait_write_buffer_empty(struct spi_sh_data *ss) -{ - int timeout = 100000; - - while (!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBE)) { - udelay(10); - if (timeout-- < 0) - return -ETIMEDOUT; - } - return 0; -} - -static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg, - struct spi_transfer *t) -{ - int i, retval = 0; - int remain = t->len; - int cur_len; - unsigned char *data; - unsigned long tmp; - long ret; - - if (t->len) - spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); - - data = (unsigned char *)t->tx_buf; - while (remain > 0) { - cur_len = min(SPI_SH_FIFO_SIZE, remain); - for (i = 0; i < cur_len && - !(spi_sh_read(ss, SPI_SH_CR4) & - SPI_SH_WPABRT) && - !(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBF); - i++) - spi_sh_write(ss, (unsigned long)data[i], SPI_SH_TBR); - - if (spi_sh_read(ss, SPI_SH_CR4) & SPI_SH_WPABRT) { - /* Abort SPI operation */ - spi_sh_set_bit(ss, SPI_SH_WPABRT, SPI_SH_CR4); - retval = -EIO; - break; - } - - cur_len = i; - - remain -= cur_len; - data += cur_len; - - if (remain > 0) { - ss->cr1 &= ~SPI_SH_TBE; - spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4); - ret = wait_event_interruptible_timeout(ss->wait, - ss->cr1 & SPI_SH_TBE, - SPI_SH_SEND_TIMEOUT); - if (ret == 0 && !(ss->cr1 & SPI_SH_TBE)) { - printk(KERN_ERR "%s: timeout\n", __func__); - return -ETIMEDOUT; - } - } - } - - if (list_is_last(&t->transfer_list, &mesg->transfers)) { - tmp = spi_sh_read(ss, SPI_SH_CR1); - tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB); - spi_sh_write(ss, tmp, SPI_SH_CR1); - spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); - - ss->cr1 &= ~SPI_SH_TBE; - spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4); - ret = wait_event_interruptible_timeout(ss->wait, - ss->cr1 & SPI_SH_TBE, - SPI_SH_SEND_TIMEOUT); - if (ret == 0 && (ss->cr1 & SPI_SH_TBE)) { - printk(KERN_ERR "%s: timeout\n", __func__); - return -ETIMEDOUT; - } - } - - return retval; -} - -static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg, - struct spi_transfer *t) -{ - int i; - int remain = t->len; - int cur_len; - unsigned char *data; - unsigned long tmp; - long ret; - - if (t->len > SPI_SH_MAX_BYTE) - spi_sh_write(ss, SPI_SH_MAX_BYTE, SPI_SH_CR3); - else - spi_sh_write(ss, t->len, SPI_SH_CR3); - - tmp = spi_sh_read(ss, SPI_SH_CR1); - tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB); - spi_sh_write(ss, tmp, SPI_SH_CR1); - spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); - - spi_sh_wait_write_buffer_empty(ss); - - data = (unsigned char *)t->rx_buf; - while (remain > 0) { - if (remain >= SPI_SH_FIFO_SIZE) { - ss->cr1 &= ~SPI_SH_RBF; - spi_sh_set_bit(ss, SPI_SH_RBF, SPI_SH_CR4); - ret = wait_event_interruptible_timeout(ss->wait, - ss->cr1 & SPI_SH_RBF, - SPI_SH_RECEIVE_TIMEOUT); - if (ret == 0 && - spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) { - printk(KERN_ERR "%s: timeout\n", __func__); - return -ETIMEDOUT; - } - } - - cur_len = min(SPI_SH_FIFO_SIZE, remain); - for (i = 0; i < cur_len; i++) { - if (spi_sh_wait_receive_buffer(ss)) - break; - data[i] = (unsigned char)spi_sh_read(ss, SPI_SH_RBR); - } - - remain -= cur_len; - data += cur_len; - } - - /* deassert CS when SPI is receiving. */ - if (t->len > SPI_SH_MAX_BYTE) { - clear_fifo(ss); - spi_sh_write(ss, 1, SPI_SH_CR3); - } else { - spi_sh_write(ss, 0, SPI_SH_CR3); - } - - return 0; -} - -static void spi_sh_work(struct work_struct *work) -{ - struct spi_sh_data *ss = container_of(work, struct spi_sh_data, ws); - struct spi_message *mesg; - struct spi_transfer *t; - unsigned long flags; - int ret; - - pr_debug("%s: enter\n", __func__); - - spin_lock_irqsave(&ss->lock, flags); - while (!list_empty(&ss->queue)) { - mesg = list_entry(ss->queue.next, struct spi_message, queue); - list_del_init(&mesg->queue); - - spin_unlock_irqrestore(&ss->lock, flags); - list_for_each_entry(t, &mesg->transfers, transfer_list) { - pr_debug("tx_buf = %p, rx_buf = %p\n", - t->tx_buf, t->rx_buf); - pr_debug("len = %d, delay_usecs = %d\n", - t->len, t->delay_usecs); - - if (t->tx_buf) { - ret = spi_sh_send(ss, mesg, t); - if (ret < 0) - goto error; - } - if (t->rx_buf) { - ret = spi_sh_receive(ss, mesg, t); - if (ret < 0) - goto error; - } - mesg->actual_length += t->len; - } - spin_lock_irqsave(&ss->lock, flags); - - mesg->status = 0; - mesg->complete(mesg->context); - } - - clear_fifo(ss); - spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1); - udelay(100); - - spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, - SPI_SH_CR1); - - clear_fifo(ss); - - spin_unlock_irqrestore(&ss->lock, flags); - - return; - - error: - mesg->status = ret; - mesg->complete(mesg->context); - - spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, - SPI_SH_CR1); - clear_fifo(ss); - -} - -static int spi_sh_setup(struct spi_device *spi) -{ - struct spi_sh_data *ss = spi_master_get_devdata(spi->master); - - if (!spi->bits_per_word) - spi->bits_per_word = 8; - - pr_debug("%s: enter\n", __func__); - - spi_sh_write(ss, 0xfe, SPI_SH_CR1); /* SPI sycle stop */ - spi_sh_write(ss, 0x00, SPI_SH_CR1); /* CR1 init */ - spi_sh_write(ss, 0x00, SPI_SH_CR3); /* CR3 init */ - - clear_fifo(ss); - - /* 1/8 clock */ - spi_sh_write(ss, spi_sh_read(ss, SPI_SH_CR2) | 0x07, SPI_SH_CR2); - udelay(10); - - return 0; -} - -static int spi_sh_transfer(struct spi_device *spi, struct spi_message *mesg) -{ - struct spi_sh_data *ss = spi_master_get_devdata(spi->master); - unsigned long flags; - - pr_debug("%s: enter\n", __func__); - pr_debug("\tmode = %02x\n", spi->mode); - - spin_lock_irqsave(&ss->lock, flags); - - mesg->actual_length = 0; - mesg->status = -EINPROGRESS; - - spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1); - - list_add_tail(&mesg->queue, &ss->queue); - queue_work(ss->workqueue, &ss->ws); - - spin_unlock_irqrestore(&ss->lock, flags); - - return 0; -} - -static void spi_sh_cleanup(struct spi_device *spi) -{ - struct spi_sh_data *ss = spi_master_get_devdata(spi->master); - - pr_debug("%s: enter\n", __func__); - - spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, - SPI_SH_CR1); -} - -static irqreturn_t spi_sh_irq(int irq, void *_ss) -{ - struct spi_sh_data *ss = (struct spi_sh_data *)_ss; - unsigned long cr1; - - cr1 = spi_sh_read(ss, SPI_SH_CR1); - if (cr1 & SPI_SH_TBE) - ss->cr1 |= SPI_SH_TBE; - if (cr1 & SPI_SH_TBF) - ss->cr1 |= SPI_SH_TBF; - if (cr1 & SPI_SH_RBE) - ss->cr1 |= SPI_SH_RBE; - if (cr1 & SPI_SH_RBF) - ss->cr1 |= SPI_SH_RBF; - - if (ss->cr1) { - spi_sh_clear_bit(ss, ss->cr1, SPI_SH_CR4); - wake_up(&ss->wait); - } - - return IRQ_HANDLED; -} - -static int __devexit spi_sh_remove(struct platform_device *pdev) -{ - struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev); - - spi_unregister_master(ss->master); - destroy_workqueue(ss->workqueue); - free_irq(ss->irq, ss); - iounmap(ss->addr); - - return 0; -} - -static int __devinit spi_sh_probe(struct platform_device *pdev) -{ - struct resource *res; - struct spi_master *master; - struct spi_sh_data *ss; - int ret, irq; - - /* get base addr */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(res == NULL)) { - dev_err(&pdev->dev, "invalid resource\n"); - return -EINVAL; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "platform_get_irq error\n"); - return -ENODEV; - } - - master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); - if (master == NULL) { - dev_err(&pdev->dev, "spi_alloc_master error.\n"); - return -ENOMEM; - } - - ss = spi_master_get_devdata(master); - dev_set_drvdata(&pdev->dev, ss); - - switch (res->flags & IORESOURCE_MEM_TYPE_MASK) { - case IORESOURCE_MEM_8BIT: - ss->width = 8; - break; - case IORESOURCE_MEM_32BIT: - ss->width = 32; - break; - default: - dev_err(&pdev->dev, "No support width\n"); - ret = -ENODEV; - goto error1; - } - ss->irq = irq; - ss->master = master; - ss->addr = ioremap(res->start, resource_size(res)); - if (ss->addr == NULL) { - dev_err(&pdev->dev, "ioremap error.\n"); - ret = -ENOMEM; - goto error1; - } - INIT_LIST_HEAD(&ss->queue); - spin_lock_init(&ss->lock); - INIT_WORK(&ss->ws, spi_sh_work); - init_waitqueue_head(&ss->wait); - ss->workqueue = create_singlethread_workqueue( - dev_name(master->dev.parent)); - if (ss->workqueue == NULL) { - dev_err(&pdev->dev, "create workqueue error\n"); - ret = -EBUSY; - goto error2; - } - - ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss); - if (ret < 0) { - dev_err(&pdev->dev, "request_irq error\n"); - goto error3; - } - - master->num_chipselect = 2; - master->bus_num = pdev->id; - master->setup = spi_sh_setup; - master->transfer = spi_sh_transfer; - master->cleanup = spi_sh_cleanup; - - ret = spi_register_master(master); - if (ret < 0) { - printk(KERN_ERR "spi_register_master error.\n"); - goto error4; - } - - return 0; - - error4: - free_irq(irq, ss); - error3: - destroy_workqueue(ss->workqueue); - error2: - iounmap(ss->addr); - error1: - spi_master_put(master); - - return ret; -} - -static struct platform_driver spi_sh_driver = { - .probe = spi_sh_probe, - .remove = __devexit_p(spi_sh_remove), - .driver = { - .name = "sh_spi", - .owner = THIS_MODULE, - }, -}; -module_platform_driver(spi_sh_driver); - -MODULE_DESCRIPTION("SH SPI bus driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Yoshihiro Shimoda"); -MODULE_ALIAS("platform:sh_spi"); |