File Index
Files and directories
Sign in
FILE

mmp_spi.c

File preview with syntax highlighting.

linux-6.19.14/drivers/video/fbdev/mmp/hw/mmp_spi.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * linux/drivers/video/mmp/hw/mmp_spi.c
  4 * using the spi in LCD controler for commands send
  5 *
  6 * Copyright (C) 2012 Marvell Technology Group Ltd.
  7 * Authors:  Guoqing Li <ligq@marvell.com>
  8 *          Lisa Du <cldu@marvell.com>
  9 *          Zhou Zhu <zzhu3@marvell.com>
 10 */
 11#include <linux/errno.h>
 12#include <linux/delay.h>
 13#include <linux/err.h>
 14#include <linux/io.h>
 15#include <linux/spi/spi.h>
 16#include "mmp_ctrl.h"
 17
 18/**
 19 * spi_write - write command to the SPI port
 20 * @spi:  the SPI device.
 21 * @data: can be 8/16/32-bit, MSB justified data to write.
 22 *
 23 * Wait bus transfer complete IRQ.
 24 * The caller is expected to perform the necessary locking.
 25 *
 26 * Returns:
 27 *   %-ETIMEDOUT	timeout occurred
 28 *   0			success
 29 */
 30static inline int lcd_spi_write(struct spi_device *spi, u32 data)
 31{
 32	int timeout = 100000, isr, ret = 0;
 33	u32 tmp;
 34	void __iomem *reg_base = (void __iomem *)
 35		*(void **) spi_controller_get_devdata(spi->controller);
 36
 37	/* clear ISR */
 38	writel_relaxed(~SPI_IRQ_MASK, reg_base + SPU_IRQ_ISR);
 39
 40	switch (spi->bits_per_word) {
 41	case 8:
 42		writel_relaxed((u8)data, reg_base + LCD_SPU_SPI_TXDATA);
 43		break;
 44	case 16:
 45		writel_relaxed((u16)data, reg_base + LCD_SPU_SPI_TXDATA);
 46		break;
 47	case 32:
 48		writel_relaxed((u32)data, reg_base + LCD_SPU_SPI_TXDATA);
 49		break;
 50	default:
 51		dev_err(&spi->dev, "Wrong spi bit length\n");
 52	}
 53
 54	/* SPI start to send command */
 55	tmp = readl_relaxed(reg_base + LCD_SPU_SPI_CTRL);
 56	tmp &= ~CFG_SPI_START_MASK;
 57	tmp |= CFG_SPI_START(1);
 58	writel(tmp, reg_base + LCD_SPU_SPI_CTRL);
 59
 60	isr = readl_relaxed(reg_base + SPU_IRQ_ISR);
 61	while (!(isr & SPI_IRQ_ENA_MASK)) {
 62		udelay(100);
 63		isr = readl_relaxed(reg_base + SPU_IRQ_ISR);
 64		if (!--timeout) {
 65			ret = -ETIMEDOUT;
 66			dev_err(&spi->dev, "spi cmd send time out\n");
 67			break;
 68		}
 69	}
 70
 71	tmp = readl_relaxed(reg_base + LCD_SPU_SPI_CTRL);
 72	tmp &= ~CFG_SPI_START_MASK;
 73	tmp |= CFG_SPI_START(0);
 74	writel_relaxed(tmp, reg_base + LCD_SPU_SPI_CTRL);
 75
 76	writel_relaxed(~SPI_IRQ_MASK, reg_base + SPU_IRQ_ISR);
 77
 78	return ret;
 79}
 80
 81static int lcd_spi_setup(struct spi_device *spi)
 82{
 83	void __iomem *reg_base = (void __iomem *)
 84		*(void **) spi_controller_get_devdata(spi->controller);
 85	u32 tmp;
 86
 87	tmp = CFG_SCLKCNT(16) |
 88		CFG_TXBITS(spi->bits_per_word) |
 89		CFG_SPI_SEL(1) | CFG_SPI_ENA(1) |
 90		CFG_SPI_3W4WB(1);
 91	writel(tmp, reg_base + LCD_SPU_SPI_CTRL);
 92
 93	/*
 94	 * After set mode it needs some time to pull up the spi signals,
 95	 * or it would cause the wrong waveform when send spi command,
 96	 * especially on pxa910h
 97	 */
 98	tmp = readl_relaxed(reg_base + SPU_IOPAD_CONTROL);
 99	if ((tmp & CFG_IOPADMODE_MASK) != IOPAD_DUMB18SPI)
100		writel_relaxed(IOPAD_DUMB18SPI |
101			(tmp & ~CFG_IOPADMODE_MASK),
102			reg_base + SPU_IOPAD_CONTROL);
103	udelay(20);
104	return 0;
105}
106
107static int lcd_spi_one_transfer(struct spi_device *spi, struct spi_message *m)
108{
109	struct spi_transfer *t;
110	int i;
111
112	list_for_each_entry(t, &m->transfers, transfer_list) {
113		switch (spi->bits_per_word) {
114		case 8:
115			for (i = 0; i < t->len; i++)
116				lcd_spi_write(spi, ((u8 *)t->tx_buf)[i]);
117			break;
118		case 16:
119			for (i = 0; i < t->len/2; i++)
120				lcd_spi_write(spi, ((u16 *)t->tx_buf)[i]);
121			break;
122		case 32:
123			for (i = 0; i < t->len/4; i++)
124				lcd_spi_write(spi, ((u32 *)t->tx_buf)[i]);
125			break;
126		default:
127			dev_err(&spi->dev, "Wrong spi bit length\n");
128		}
129	}
130
131	m->status = 0;
132	if (m->complete)
133		m->complete(m->context);
134	return 0;
135}
136
137int lcd_spi_register(struct mmphw_ctrl *ctrl)
138{
139	struct spi_controller *ctlr;
140	void **p_regbase;
141	int err;
142
143	ctlr = spi_alloc_host(ctrl->dev, sizeof(void *));
144	if (!ctlr) {
145		dev_err(ctrl->dev, "unable to allocate SPI host\n");
146		return -ENOMEM;
147	}
148	p_regbase = spi_controller_get_devdata(ctlr);
149	*p_regbase = (void __force *)ctrl->reg_base;
150
151	/* set bus num to 5 to avoid conflict with other spi hosts */
152	ctlr->bus_num = 5;
153	ctlr->num_chipselect = 1;
154	ctlr->setup = lcd_spi_setup;
155	ctlr->transfer = lcd_spi_one_transfer;
156
157	err = spi_register_controller(ctlr);
158	if (err < 0) {
159		dev_err(ctrl->dev, "unable to register SPI host\n");
160		spi_controller_put(ctlr);
161		return err;
162	}
163
164	dev_info(&ctlr->dev, "registered\n");
165
166	return 0;
167}
~/ Read-only file preview.