brintos

brintos / linux-shallow public Read only

0
0
Text · 4.1 KiB · cf23650 Raw
168 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * linux/drivers/video/mmp/hw/mmp_spi.c4 * using the spi in LCD controler for commands send5 *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 port20 * @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 occurred28 *   0			success29 */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 pxa910h97	 */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_master(ctrl->dev, sizeof(void *));144	if (!ctlr) {145		dev_err(ctrl->dev, "unable to allocate SPI master\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 master\n");160		spi_controller_put(ctlr);161		return err;162	}163 164	dev_info(&ctlr->dev, "registered\n");165 166	return 0;167}168