brintos

brintos / linux-shallow public Read only

0
0
Text · 10.2 KiB · 4b873d9 Raw
473 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * SH SPI bus driver4 *5 * Copyright (C) 2011  Renesas Solutions Corp.6 *7 * Based on pxa2xx_spi.c:8 * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs9 */10 11#include <linux/module.h>12#include <linux/kernel.h>13#include <linux/sched.h>14#include <linux/errno.h>15#include <linux/timer.h>16#include <linux/delay.h>17#include <linux/list.h>18#include <linux/workqueue.h>19#include <linux/interrupt.h>20#include <linux/platform_device.h>21#include <linux/io.h>22#include <linux/spi/spi.h>23 24#define SPI_SH_TBR		0x0025#define SPI_SH_RBR		0x0026#define SPI_SH_CR1		0x0827#define SPI_SH_CR2		0x1028#define SPI_SH_CR3		0x1829#define SPI_SH_CR4		0x2030#define SPI_SH_CR5		0x2831 32/* CR1 */33#define SPI_SH_TBE		0x8034#define SPI_SH_TBF		0x4035#define SPI_SH_RBE		0x2036#define SPI_SH_RBF		0x1037#define SPI_SH_PFONRD		0x0838#define SPI_SH_SSDB		0x0439#define SPI_SH_SSD		0x0240#define SPI_SH_SSA		0x0141 42/* CR2 */43#define SPI_SH_RSTF		0x8044#define SPI_SH_LOOPBK		0x4045#define SPI_SH_CPOL		0x2046#define SPI_SH_CPHA		0x1047#define SPI_SH_L1M0		0x0848 49/* CR3 */50#define SPI_SH_MAX_BYTE		0xFF51 52/* CR4 */53#define SPI_SH_TBEI		0x8054#define SPI_SH_TBFI		0x4055#define SPI_SH_RBEI		0x2056#define SPI_SH_RBFI		0x1057#define SPI_SH_WPABRT		0x0458#define SPI_SH_SSS		0x0159 60/* CR8 */61#define SPI_SH_P1L0		0x8062#define SPI_SH_PP1L0		0x4063#define SPI_SH_MUXI		0x2064#define SPI_SH_MUXIRQ		0x1065 66#define SPI_SH_FIFO_SIZE	3267#define SPI_SH_SEND_TIMEOUT	(3 * HZ)68#define SPI_SH_RECEIVE_TIMEOUT	(HZ >> 3)69 70#undef DEBUG71 72struct spi_sh_data {73	void __iomem *addr;74	int irq;75	struct spi_controller *host;76	unsigned long cr1;77	wait_queue_head_t wait;78	int width;79};80 81static void spi_sh_write(struct spi_sh_data *ss, unsigned long data,82			     unsigned long offset)83{84	if (ss->width == 8)85		iowrite8(data, ss->addr + (offset >> 2));86	else if (ss->width == 32)87		iowrite32(data, ss->addr + offset);88}89 90static unsigned long spi_sh_read(struct spi_sh_data *ss, unsigned long offset)91{92	if (ss->width == 8)93		return ioread8(ss->addr + (offset >> 2));94	else if (ss->width == 32)95		return ioread32(ss->addr + offset);96	else97		return 0;98}99 100static void spi_sh_set_bit(struct spi_sh_data *ss, unsigned long val,101				unsigned long offset)102{103	unsigned long tmp;104 105	tmp = spi_sh_read(ss, offset);106	tmp |= val;107	spi_sh_write(ss, tmp, offset);108}109 110static void spi_sh_clear_bit(struct spi_sh_data *ss, unsigned long val,111				unsigned long offset)112{113	unsigned long tmp;114 115	tmp = spi_sh_read(ss, offset);116	tmp &= ~val;117	spi_sh_write(ss, tmp, offset);118}119 120static void clear_fifo(struct spi_sh_data *ss)121{122	spi_sh_set_bit(ss, SPI_SH_RSTF, SPI_SH_CR2);123	spi_sh_clear_bit(ss, SPI_SH_RSTF, SPI_SH_CR2);124}125 126static int spi_sh_wait_receive_buffer(struct spi_sh_data *ss)127{128	int timeout = 100000;129 130	while (spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) {131		udelay(10);132		if (timeout-- < 0)133			return -ETIMEDOUT;134	}135	return 0;136}137 138static int spi_sh_wait_write_buffer_empty(struct spi_sh_data *ss)139{140	int timeout = 100000;141 142	while (!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBE)) {143		udelay(10);144		if (timeout-- < 0)145			return -ETIMEDOUT;146	}147	return 0;148}149 150static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg,151			struct spi_transfer *t)152{153	int i, retval = 0;154	int remain = t->len;155	int cur_len;156	unsigned char *data;157	long ret;158 159	if (t->len)160		spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);161 162	data = (unsigned char *)t->tx_buf;163	while (remain > 0) {164		cur_len = min(SPI_SH_FIFO_SIZE, remain);165		for (i = 0; i < cur_len &&166				!(spi_sh_read(ss, SPI_SH_CR4) &167							SPI_SH_WPABRT) &&168				!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBF);169				i++)170			spi_sh_write(ss, (unsigned long)data[i], SPI_SH_TBR);171 172		if (spi_sh_read(ss, SPI_SH_CR4) & SPI_SH_WPABRT) {173			/* Abort SPI operation */174			spi_sh_set_bit(ss, SPI_SH_WPABRT, SPI_SH_CR4);175			retval = -EIO;176			break;177		}178 179		cur_len = i;180 181		remain -= cur_len;182		data += cur_len;183 184		if (remain > 0) {185			ss->cr1 &= ~SPI_SH_TBE;186			spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4);187			ret = wait_event_interruptible_timeout(ss->wait,188						 ss->cr1 & SPI_SH_TBE,189						 SPI_SH_SEND_TIMEOUT);190			if (ret == 0 && !(ss->cr1 & SPI_SH_TBE)) {191				printk(KERN_ERR "%s: timeout\n", __func__);192				return -ETIMEDOUT;193			}194		}195	}196 197	if (list_is_last(&t->transfer_list, &mesg->transfers)) {198		spi_sh_clear_bit(ss, SPI_SH_SSD | SPI_SH_SSDB, SPI_SH_CR1);199		spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);200 201		ss->cr1 &= ~SPI_SH_TBE;202		spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4);203		ret = wait_event_interruptible_timeout(ss->wait,204					 ss->cr1 & SPI_SH_TBE,205					 SPI_SH_SEND_TIMEOUT);206		if (ret == 0 && (ss->cr1 & SPI_SH_TBE)) {207			printk(KERN_ERR "%s: timeout\n", __func__);208			return -ETIMEDOUT;209		}210	}211 212	return retval;213}214 215static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg,216			  struct spi_transfer *t)217{218	int i;219	int remain = t->len;220	int cur_len;221	unsigned char *data;222	long ret;223 224	if (t->len > SPI_SH_MAX_BYTE)225		spi_sh_write(ss, SPI_SH_MAX_BYTE, SPI_SH_CR3);226	else227		spi_sh_write(ss, t->len, SPI_SH_CR3);228 229	spi_sh_clear_bit(ss, SPI_SH_SSD | SPI_SH_SSDB, SPI_SH_CR1);230	spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);231 232	spi_sh_wait_write_buffer_empty(ss);233 234	data = (unsigned char *)t->rx_buf;235	while (remain > 0) {236		if (remain >= SPI_SH_FIFO_SIZE) {237			ss->cr1 &= ~SPI_SH_RBF;238			spi_sh_set_bit(ss, SPI_SH_RBF, SPI_SH_CR4);239			ret = wait_event_interruptible_timeout(ss->wait,240						 ss->cr1 & SPI_SH_RBF,241						 SPI_SH_RECEIVE_TIMEOUT);242			if (ret == 0 &&243			    spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) {244				printk(KERN_ERR "%s: timeout\n", __func__);245				return -ETIMEDOUT;246			}247		}248 249		cur_len = min(SPI_SH_FIFO_SIZE, remain);250		for (i = 0; i < cur_len; i++) {251			if (spi_sh_wait_receive_buffer(ss))252				break;253			data[i] = (unsigned char)spi_sh_read(ss, SPI_SH_RBR);254		}255 256		remain -= cur_len;257		data += cur_len;258	}259 260	/* deassert CS when SPI is receiving. */261	if (t->len > SPI_SH_MAX_BYTE) {262		clear_fifo(ss);263		spi_sh_write(ss, 1, SPI_SH_CR3);264	} else {265		spi_sh_write(ss, 0, SPI_SH_CR3);266	}267 268	return 0;269}270 271static int spi_sh_transfer_one_message(struct spi_controller *ctlr,272					struct spi_message *mesg)273{274	struct spi_sh_data *ss = spi_controller_get_devdata(ctlr);275	struct spi_transfer *t;276	int ret;277 278	pr_debug("%s: enter\n", __func__);279 280	spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1);281 282	list_for_each_entry(t, &mesg->transfers, transfer_list) {283		pr_debug("tx_buf = %p, rx_buf = %p\n",284			 t->tx_buf, t->rx_buf);285		pr_debug("len = %d, delay.value = %d\n",286			 t->len, t->delay.value);287 288		if (t->tx_buf) {289			ret = spi_sh_send(ss, mesg, t);290			if (ret < 0)291				goto error;292		}293		if (t->rx_buf) {294			ret = spi_sh_receive(ss, mesg, t);295			if (ret < 0)296				goto error;297		}298		mesg->actual_length += t->len;299	}300 301	mesg->status = 0;302	spi_finalize_current_message(ctlr);303 304	clear_fifo(ss);305	spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1);306	udelay(100);307 308	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,309			 SPI_SH_CR1);310 311	clear_fifo(ss);312 313	return 0;314 315 error:316	mesg->status = ret;317	spi_finalize_current_message(ctlr);318	if (mesg->complete)319		mesg->complete(mesg->context);320 321	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,322			 SPI_SH_CR1);323	clear_fifo(ss);324 325	return ret;326}327 328static int spi_sh_setup(struct spi_device *spi)329{330	struct spi_sh_data *ss = spi_controller_get_devdata(spi->controller);331 332	pr_debug("%s: enter\n", __func__);333 334	spi_sh_write(ss, 0xfe, SPI_SH_CR1);	/* SPI sycle stop */335	spi_sh_write(ss, 0x00, SPI_SH_CR1);	/* CR1 init */336	spi_sh_write(ss, 0x00, SPI_SH_CR3);	/* CR3 init */337 338	clear_fifo(ss);339 340	/* 1/8 clock */341	spi_sh_write(ss, spi_sh_read(ss, SPI_SH_CR2) | 0x07, SPI_SH_CR2);342	udelay(10);343 344	return 0;345}346 347static void spi_sh_cleanup(struct spi_device *spi)348{349	struct spi_sh_data *ss = spi_controller_get_devdata(spi->controller);350 351	pr_debug("%s: enter\n", __func__);352 353	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,354			 SPI_SH_CR1);355}356 357static irqreturn_t spi_sh_irq(int irq, void *_ss)358{359	struct spi_sh_data *ss = (struct spi_sh_data *)_ss;360	unsigned long cr1;361 362	cr1 = spi_sh_read(ss, SPI_SH_CR1);363	if (cr1 & SPI_SH_TBE)364		ss->cr1 |= SPI_SH_TBE;365	if (cr1 & SPI_SH_TBF)366		ss->cr1 |= SPI_SH_TBF;367	if (cr1 & SPI_SH_RBE)368		ss->cr1 |= SPI_SH_RBE;369	if (cr1 & SPI_SH_RBF)370		ss->cr1 |= SPI_SH_RBF;371 372	if (ss->cr1) {373		spi_sh_clear_bit(ss, ss->cr1, SPI_SH_CR4);374		wake_up(&ss->wait);375	}376 377	return IRQ_HANDLED;378}379 380static void spi_sh_remove(struct platform_device *pdev)381{382	struct spi_sh_data *ss = platform_get_drvdata(pdev);383 384	spi_unregister_controller(ss->host);385	free_irq(ss->irq, ss);386}387 388static int spi_sh_probe(struct platform_device *pdev)389{390	struct resource *res;391	struct spi_controller *host;392	struct spi_sh_data *ss;393	int ret, irq;394 395	/* get base addr */396	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);397	if (unlikely(res == NULL)) {398		dev_err(&pdev->dev, "invalid resource\n");399		return -EINVAL;400	}401 402	irq = platform_get_irq(pdev, 0);403	if (irq < 0)404		return irq;405 406	host = devm_spi_alloc_host(&pdev->dev, sizeof(struct spi_sh_data));407	if (host == NULL) {408		dev_err(&pdev->dev, "devm_spi_alloc_host error.\n");409		return -ENOMEM;410	}411 412	ss = spi_controller_get_devdata(host);413	platform_set_drvdata(pdev, ss);414 415	switch (res->flags & IORESOURCE_MEM_TYPE_MASK) {416	case IORESOURCE_MEM_8BIT:417		ss->width = 8;418		break;419	case IORESOURCE_MEM_32BIT:420		ss->width = 32;421		break;422	default:423		dev_err(&pdev->dev, "No support width\n");424		return -ENODEV;425	}426	ss->irq = irq;427	ss->host = host;428	ss->addr = devm_ioremap(&pdev->dev, res->start, resource_size(res));429	if (ss->addr == NULL) {430		dev_err(&pdev->dev, "ioremap error.\n");431		return -ENOMEM;432	}433	init_waitqueue_head(&ss->wait);434 435	ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss);436	if (ret < 0) {437		dev_err(&pdev->dev, "request_irq error\n");438		return ret;439	}440 441	host->num_chipselect = 2;442	host->bus_num = pdev->id;443	host->setup = spi_sh_setup;444	host->transfer_one_message = spi_sh_transfer_one_message;445	host->cleanup = spi_sh_cleanup;446 447	ret = spi_register_controller(host);448	if (ret < 0) {449		printk(KERN_ERR "spi_register_controller error.\n");450		goto error3;451	}452 453	return 0;454 455 error3:456	free_irq(irq, ss);457	return ret;458}459 460static struct platform_driver spi_sh_driver = {461	.probe = spi_sh_probe,462	.remove_new = spi_sh_remove,463	.driver = {464		.name = "sh_spi",465	},466};467module_platform_driver(spi_sh_driver);468 469MODULE_DESCRIPTION("SH SPI bus driver");470MODULE_LICENSE("GPL v2");471MODULE_AUTHOR("Yoshihiro Shimoda");472MODULE_ALIAS("platform:sh_spi");473