xref: /linux/drivers/video/fbdev/mmp/hw/mmp_spi.c (revision d0034a7a4ac7fae708146ac0059b9c47a1543f0d)
11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2641b4b1bSZhou Zhu /*
3641b4b1bSZhou Zhu  * linux/drivers/video/mmp/hw/mmp_spi.c
4641b4b1bSZhou Zhu  * using the spi in LCD controler for commands send
5641b4b1bSZhou Zhu  *
6641b4b1bSZhou Zhu  * Copyright (C) 2012 Marvell Technology Group Ltd.
7641b4b1bSZhou Zhu  * Authors:  Guoqing Li <ligq@marvell.com>
8641b4b1bSZhou Zhu  *          Lisa Du <cldu@marvell.com>
9641b4b1bSZhou Zhu  *          Zhou Zhu <zzhu3@marvell.com>
10641b4b1bSZhou Zhu  */
11641b4b1bSZhou Zhu #include <linux/errno.h>
12641b4b1bSZhou Zhu #include <linux/delay.h>
13641b4b1bSZhou Zhu #include <linux/err.h>
14641b4b1bSZhou Zhu #include <linux/io.h>
15641b4b1bSZhou Zhu #include <linux/spi/spi.h>
16641b4b1bSZhou Zhu #include "mmp_ctrl.h"
17641b4b1bSZhou Zhu 
18641b4b1bSZhou Zhu /**
19641b4b1bSZhou Zhu  * spi_write - write command to the SPI port
20*031d039fSSam Ravnborg  * @spi:  the SPI device.
21641b4b1bSZhou Zhu  * @data: can be 8/16/32-bit, MSB justified data to write.
22641b4b1bSZhou Zhu  *
23641b4b1bSZhou Zhu  * Wait bus transfer complete IRQ.
24641b4b1bSZhou Zhu  * The caller is expected to perform the necessary locking.
25641b4b1bSZhou Zhu  *
26641b4b1bSZhou Zhu  * Returns:
27641b4b1bSZhou Zhu  *   %-ETIMEDOUT	timeout occurred
28641b4b1bSZhou Zhu  *   0			success
29641b4b1bSZhou Zhu  */
30641b4b1bSZhou Zhu static inline int lcd_spi_write(struct spi_device *spi, u32 data)
31641b4b1bSZhou Zhu {
32641b4b1bSZhou Zhu 	int timeout = 100000, isr, ret = 0;
33641b4b1bSZhou Zhu 	u32 tmp;
34e41f6b17SBartlomiej Zolnierkiewicz 	void __iomem *reg_base = (void __iomem *)
35641b4b1bSZhou Zhu 		*(void **)spi_master_get_devdata(spi->master);
36641b4b1bSZhou Zhu 
37641b4b1bSZhou Zhu 	/* clear ISR */
38641b4b1bSZhou Zhu 	writel_relaxed(~SPI_IRQ_MASK, reg_base + SPU_IRQ_ISR);
39641b4b1bSZhou Zhu 
40641b4b1bSZhou Zhu 	switch (spi->bits_per_word) {
41641b4b1bSZhou Zhu 	case 8:
42641b4b1bSZhou Zhu 		writel_relaxed((u8)data, reg_base + LCD_SPU_SPI_TXDATA);
43641b4b1bSZhou Zhu 		break;
44641b4b1bSZhou Zhu 	case 16:
45641b4b1bSZhou Zhu 		writel_relaxed((u16)data, reg_base + LCD_SPU_SPI_TXDATA);
46641b4b1bSZhou Zhu 		break;
47641b4b1bSZhou Zhu 	case 32:
48641b4b1bSZhou Zhu 		writel_relaxed((u32)data, reg_base + LCD_SPU_SPI_TXDATA);
49641b4b1bSZhou Zhu 		break;
50641b4b1bSZhou Zhu 	default:
51641b4b1bSZhou Zhu 		dev_err(&spi->dev, "Wrong spi bit length\n");
52641b4b1bSZhou Zhu 	}
53641b4b1bSZhou Zhu 
54641b4b1bSZhou Zhu 	/* SPI start to send command */
55641b4b1bSZhou Zhu 	tmp = readl_relaxed(reg_base + LCD_SPU_SPI_CTRL);
56641b4b1bSZhou Zhu 	tmp &= ~CFG_SPI_START_MASK;
57641b4b1bSZhou Zhu 	tmp |= CFG_SPI_START(1);
58641b4b1bSZhou Zhu 	writel(tmp, reg_base + LCD_SPU_SPI_CTRL);
59641b4b1bSZhou Zhu 
60641b4b1bSZhou Zhu 	isr = readl_relaxed(reg_base + SPU_IRQ_ISR);
61641b4b1bSZhou Zhu 	while (!(isr & SPI_IRQ_ENA_MASK)) {
62641b4b1bSZhou Zhu 		udelay(100);
63641b4b1bSZhou Zhu 		isr = readl_relaxed(reg_base + SPU_IRQ_ISR);
64641b4b1bSZhou Zhu 		if (!--timeout) {
65641b4b1bSZhou Zhu 			ret = -ETIMEDOUT;
66641b4b1bSZhou Zhu 			dev_err(&spi->dev, "spi cmd send time out\n");
67641b4b1bSZhou Zhu 			break;
68641b4b1bSZhou Zhu 		}
69641b4b1bSZhou Zhu 	}
70641b4b1bSZhou Zhu 
71641b4b1bSZhou Zhu 	tmp = readl_relaxed(reg_base + LCD_SPU_SPI_CTRL);
72641b4b1bSZhou Zhu 	tmp &= ~CFG_SPI_START_MASK;
73641b4b1bSZhou Zhu 	tmp |= CFG_SPI_START(0);
74641b4b1bSZhou Zhu 	writel_relaxed(tmp, reg_base + LCD_SPU_SPI_CTRL);
75641b4b1bSZhou Zhu 
76641b4b1bSZhou Zhu 	writel_relaxed(~SPI_IRQ_MASK, reg_base + SPU_IRQ_ISR);
77641b4b1bSZhou Zhu 
78641b4b1bSZhou Zhu 	return ret;
79641b4b1bSZhou Zhu }
80641b4b1bSZhou Zhu 
81641b4b1bSZhou Zhu static int lcd_spi_setup(struct spi_device *spi)
82641b4b1bSZhou Zhu {
83e41f6b17SBartlomiej Zolnierkiewicz 	void __iomem *reg_base = (void __iomem *)
84641b4b1bSZhou Zhu 		*(void **)spi_master_get_devdata(spi->master);
85641b4b1bSZhou Zhu 	u32 tmp;
86641b4b1bSZhou Zhu 
87641b4b1bSZhou Zhu 	tmp = CFG_SCLKCNT(16) |
88641b4b1bSZhou Zhu 		CFG_TXBITS(spi->bits_per_word) |
89641b4b1bSZhou Zhu 		CFG_SPI_SEL(1) | CFG_SPI_ENA(1) |
90641b4b1bSZhou Zhu 		CFG_SPI_3W4WB(1);
91641b4b1bSZhou Zhu 	writel(tmp, reg_base + LCD_SPU_SPI_CTRL);
92641b4b1bSZhou Zhu 
93641b4b1bSZhou Zhu 	/*
94641b4b1bSZhou Zhu 	 * After set mode it need a time to pull up the spi singals,
95641b4b1bSZhou Zhu 	 * or it would cause the wrong waveform when send spi command,
96641b4b1bSZhou Zhu 	 * especially on pxa910h
97641b4b1bSZhou Zhu 	 */
98641b4b1bSZhou Zhu 	tmp = readl_relaxed(reg_base + SPU_IOPAD_CONTROL);
99641b4b1bSZhou Zhu 	if ((tmp & CFG_IOPADMODE_MASK) != IOPAD_DUMB18SPI)
100641b4b1bSZhou Zhu 		writel_relaxed(IOPAD_DUMB18SPI |
101641b4b1bSZhou Zhu 			(tmp & ~CFG_IOPADMODE_MASK),
102641b4b1bSZhou Zhu 			reg_base + SPU_IOPAD_CONTROL);
103641b4b1bSZhou Zhu 	udelay(20);
104641b4b1bSZhou Zhu 	return 0;
105641b4b1bSZhou Zhu }
106641b4b1bSZhou Zhu 
107641b4b1bSZhou Zhu static int lcd_spi_one_transfer(struct spi_device *spi, struct spi_message *m)
108641b4b1bSZhou Zhu {
109641b4b1bSZhou Zhu 	struct spi_transfer *t;
110641b4b1bSZhou Zhu 	int i;
111641b4b1bSZhou Zhu 
112641b4b1bSZhou Zhu 	list_for_each_entry(t, &m->transfers, transfer_list) {
113641b4b1bSZhou Zhu 		switch (spi->bits_per_word) {
114641b4b1bSZhou Zhu 		case 8:
115641b4b1bSZhou Zhu 			for (i = 0; i < t->len; i++)
116641b4b1bSZhou Zhu 				lcd_spi_write(spi, ((u8 *)t->tx_buf)[i]);
117641b4b1bSZhou Zhu 			break;
118641b4b1bSZhou Zhu 		case 16:
119641b4b1bSZhou Zhu 			for (i = 0; i < t->len/2; i++)
120641b4b1bSZhou Zhu 				lcd_spi_write(spi, ((u16 *)t->tx_buf)[i]);
121641b4b1bSZhou Zhu 			break;
122641b4b1bSZhou Zhu 		case 32:
123641b4b1bSZhou Zhu 			for (i = 0; i < t->len/4; i++)
124641b4b1bSZhou Zhu 				lcd_spi_write(spi, ((u32 *)t->tx_buf)[i]);
125641b4b1bSZhou Zhu 			break;
126641b4b1bSZhou Zhu 		default:
127641b4b1bSZhou Zhu 			dev_err(&spi->dev, "Wrong spi bit length\n");
128641b4b1bSZhou Zhu 		}
129641b4b1bSZhou Zhu 	}
130641b4b1bSZhou Zhu 
131641b4b1bSZhou Zhu 	m->status = 0;
132641b4b1bSZhou Zhu 	if (m->complete)
133641b4b1bSZhou Zhu 		m->complete(m->context);
134641b4b1bSZhou Zhu 	return 0;
135641b4b1bSZhou Zhu }
136641b4b1bSZhou Zhu 
137641b4b1bSZhou Zhu int lcd_spi_register(struct mmphw_ctrl *ctrl)
138641b4b1bSZhou Zhu {
139641b4b1bSZhou Zhu 	struct spi_master *master;
140641b4b1bSZhou Zhu 	void **p_regbase;
141641b4b1bSZhou Zhu 	int err;
142641b4b1bSZhou Zhu 
143641b4b1bSZhou Zhu 	master = spi_alloc_master(ctrl->dev, sizeof(void *));
144641b4b1bSZhou Zhu 	if (!master) {
145641b4b1bSZhou Zhu 		dev_err(ctrl->dev, "unable to allocate SPI master\n");
146641b4b1bSZhou Zhu 		return -ENOMEM;
147641b4b1bSZhou Zhu 	}
148641b4b1bSZhou Zhu 	p_regbase = spi_master_get_devdata(master);
149e41f6b17SBartlomiej Zolnierkiewicz 	*p_regbase = (void __force *)ctrl->reg_base;
150641b4b1bSZhou Zhu 
151641b4b1bSZhou Zhu 	/* set bus num to 5 to avoid conflict with other spi hosts */
152641b4b1bSZhou Zhu 	master->bus_num = 5;
153641b4b1bSZhou Zhu 	master->num_chipselect = 1;
154641b4b1bSZhou Zhu 	master->setup = lcd_spi_setup;
155641b4b1bSZhou Zhu 	master->transfer = lcd_spi_one_transfer;
156641b4b1bSZhou Zhu 
157641b4b1bSZhou Zhu 	err = spi_register_master(master);
158641b4b1bSZhou Zhu 	if (err < 0) {
159641b4b1bSZhou Zhu 		dev_err(ctrl->dev, "unable to register SPI master\n");
160641b4b1bSZhou Zhu 		spi_master_put(master);
161641b4b1bSZhou Zhu 		return err;
162641b4b1bSZhou Zhu 	}
163641b4b1bSZhou Zhu 
164641b4b1bSZhou Zhu 	dev_info(&master->dev, "registered\n");
165641b4b1bSZhou Zhu 
166641b4b1bSZhou Zhu 	return 0;
167641b4b1bSZhou Zhu }
168