xref: /openbmc/linux/drivers/spi/spi-fsl-spi.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2ca632f55SGrant Likely /*
3ca632f55SGrant Likely  * Freescale SPI controller driver.
4ca632f55SGrant Likely  *
5ca632f55SGrant Likely  * Maintainer: Kumar Gala
6ca632f55SGrant Likely  *
7ca632f55SGrant Likely  * Copyright (C) 2006 Polycom, Inc.
8ca632f55SGrant Likely  * Copyright 2010 Freescale Semiconductor, Inc.
9ca632f55SGrant Likely  *
10ca632f55SGrant Likely  * CPM SPI and QE buffer descriptors mode support:
11ca632f55SGrant Likely  * Copyright (c) 2009  MontaVista Software, Inc.
12ca632f55SGrant Likely  * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
13ca632f55SGrant Likely  *
14447b0c7bSAndreas Larsson  * GRLIB support:
15447b0c7bSAndreas Larsson  * Copyright (c) 2012 Aeroflex Gaisler AB.
16447b0c7bSAndreas Larsson  * Author: Andreas Larsson <andreas@gaisler.com>
17ca632f55SGrant Likely  */
18ca632f55SGrant Likely #include <linux/delay.h>
19ca632f55SGrant Likely #include <linux/dma-mapping.h>
20a3108360SXiubo Li #include <linux/fsl_devices.h>
210f0581b2SLinus Walleij #include <linux/gpio/consumer.h>
22a3108360SXiubo Li #include <linux/interrupt.h>
23a3108360SXiubo Li #include <linux/irq.h>
24a3108360SXiubo Li #include <linux/kernel.h>
25ca632f55SGrant Likely #include <linux/mm.h>
26a3108360SXiubo Li #include <linux/module.h>
27ca632f55SGrant Likely #include <linux/mutex.h>
28ca632f55SGrant Likely #include <linux/of.h>
29e8beacbbSAndreas Larsson #include <linux/of_address.h>
30e8beacbbSAndreas Larsson #include <linux/of_irq.h>
31a3108360SXiubo Li #include <linux/of_platform.h>
32a3108360SXiubo Li #include <linux/platform_device.h>
33a3108360SXiubo Li #include <linux/spi/spi.h>
34a3108360SXiubo Li #include <linux/spi/spi_bitbang.h>
35a3108360SXiubo Li #include <linux/types.h>
36ca632f55SGrant Likely 
3769b921acSRasmus Villemoes #ifdef CONFIG_FSL_SOC
3869b921acSRasmus Villemoes #include <sysdev/fsl_soc.h>
3969b921acSRasmus Villemoes #endif
4069b921acSRasmus Villemoes 
4169b921acSRasmus Villemoes /* Specific to the MPC8306/MPC8309 */
4269b921acSRasmus Villemoes #define IMMR_SPI_CS_OFFSET 0x14c
4369b921acSRasmus Villemoes #define SPI_BOOT_SEL_BIT   0x80000000
4469b921acSRasmus Villemoes 
45ca632f55SGrant Likely #include "spi-fsl-lib.h"
46e8beacbbSAndreas Larsson #include "spi-fsl-cpm.h"
47e8beacbbSAndreas Larsson #include "spi-fsl-spi.h"
48ca632f55SGrant Likely 
49c3f3e771SAndreas Larsson #define TYPE_FSL	0
50447b0c7bSAndreas Larsson #define TYPE_GRLIB	1
51c3f3e771SAndreas Larsson 
52c3f3e771SAndreas Larsson struct fsl_spi_match_data {
53c3f3e771SAndreas Larsson 	int type;
54c3f3e771SAndreas Larsson };
55c3f3e771SAndreas Larsson 
56c3f3e771SAndreas Larsson static struct fsl_spi_match_data of_fsl_spi_fsl_config = {
57c3f3e771SAndreas Larsson 	.type = TYPE_FSL,
58c3f3e771SAndreas Larsson };
59c3f3e771SAndreas Larsson 
60447b0c7bSAndreas Larsson static struct fsl_spi_match_data of_fsl_spi_grlib_config = {
61447b0c7bSAndreas Larsson 	.type = TYPE_GRLIB,
62447b0c7bSAndreas Larsson };
63447b0c7bSAndreas Larsson 
643aea901dSJingoo Han static const struct of_device_id of_fsl_spi_match[] = {
65c3f3e771SAndreas Larsson 	{
66c3f3e771SAndreas Larsson 		.compatible = "fsl,spi",
67c3f3e771SAndreas Larsson 		.data = &of_fsl_spi_fsl_config,
68c3f3e771SAndreas Larsson 	},
69447b0c7bSAndreas Larsson 	{
70447b0c7bSAndreas Larsson 		.compatible = "aeroflexgaisler,spictrl",
71447b0c7bSAndreas Larsson 		.data = &of_fsl_spi_grlib_config,
72447b0c7bSAndreas Larsson 	},
73c3f3e771SAndreas Larsson 	{}
74c3f3e771SAndreas Larsson };
75c3f3e771SAndreas Larsson MODULE_DEVICE_TABLE(of, of_fsl_spi_match);
76c3f3e771SAndreas Larsson 
fsl_spi_get_type(struct device * dev)77c3f3e771SAndreas Larsson static int fsl_spi_get_type(struct device *dev)
78c3f3e771SAndreas Larsson {
79c3f3e771SAndreas Larsson 	const struct of_device_id *match;
80c3f3e771SAndreas Larsson 
81c3f3e771SAndreas Larsson 	if (dev->of_node) {
82c3f3e771SAndreas Larsson 		match = of_match_node(of_fsl_spi_match, dev->of_node);
83c3f3e771SAndreas Larsson 		if (match && match->data)
84c3f3e771SAndreas Larsson 			return ((struct fsl_spi_match_data *)match->data)->type;
85c3f3e771SAndreas Larsson 	}
86c3f3e771SAndreas Larsson 	return TYPE_FSL;
87c3f3e771SAndreas Larsson }
88c3f3e771SAndreas Larsson 
fsl_spi_change_mode(struct spi_device * spi)89ca632f55SGrant Likely static void fsl_spi_change_mode(struct spi_device *spi)
90ca632f55SGrant Likely {
91*d32382caSYang Yingliang 	struct mpc8xxx_spi *mspi = spi_controller_get_devdata(spi->controller);
92ca632f55SGrant Likely 	struct spi_mpc8xxx_cs *cs = spi->controller_state;
93dd67de8cSLuc Van Oostenryck 	struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
94ca632f55SGrant Likely 	__be32 __iomem *mode = &reg_base->mode;
95ca632f55SGrant Likely 	unsigned long flags;
96ca632f55SGrant Likely 
97ca632f55SGrant Likely 	if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
98ca632f55SGrant Likely 		return;
99ca632f55SGrant Likely 
100ca632f55SGrant Likely 	/* Turn off IRQs locally to minimize time that SPI is disabled. */
101ca632f55SGrant Likely 	local_irq_save(flags);
102ca632f55SGrant Likely 
103ca632f55SGrant Likely 	/* Turn off SPI unit prior changing mode */
104ca632f55SGrant Likely 	mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
105ca632f55SGrant Likely 
106ca632f55SGrant Likely 	/* When in CPM mode, we need to reinit tx and rx. */
107ca632f55SGrant Likely 	if (mspi->flags & SPI_CPM_MODE) {
108e8beacbbSAndreas Larsson 		fsl_spi_cpm_reinit_txrx(mspi);
109ca632f55SGrant Likely 	}
110ca632f55SGrant Likely 	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
111ca632f55SGrant Likely 	local_irq_restore(flags);
112ca632f55SGrant Likely }
113ca632f55SGrant Likely 
fsl_spi_qe_cpu_set_shifts(u32 * rx_shift,u32 * tx_shift,int bits_per_word,int msb_first)114b48c4e3cSAndreas Larsson static void fsl_spi_qe_cpu_set_shifts(u32 *rx_shift, u32 *tx_shift,
115b48c4e3cSAndreas Larsson 				      int bits_per_word, int msb_first)
116b48c4e3cSAndreas Larsson {
117b48c4e3cSAndreas Larsson 	*rx_shift = 0;
118b48c4e3cSAndreas Larsson 	*tx_shift = 0;
119b48c4e3cSAndreas Larsson 	if (msb_first) {
120b48c4e3cSAndreas Larsson 		if (bits_per_word <= 8) {
121b48c4e3cSAndreas Larsson 			*rx_shift = 16;
122b48c4e3cSAndreas Larsson 			*tx_shift = 24;
123b48c4e3cSAndreas Larsson 		} else if (bits_per_word <= 16) {
124b48c4e3cSAndreas Larsson 			*rx_shift = 16;
125b48c4e3cSAndreas Larsson 			*tx_shift = 16;
126b48c4e3cSAndreas Larsson 		}
127b48c4e3cSAndreas Larsson 	} else {
128b48c4e3cSAndreas Larsson 		if (bits_per_word <= 8)
129b48c4e3cSAndreas Larsson 			*rx_shift = 8;
130b48c4e3cSAndreas Larsson 	}
131b48c4e3cSAndreas Larsson }
132b48c4e3cSAndreas Larsson 
fsl_spi_grlib_set_shifts(u32 * rx_shift,u32 * tx_shift,int bits_per_word,int msb_first)133447b0c7bSAndreas Larsson static void fsl_spi_grlib_set_shifts(u32 *rx_shift, u32 *tx_shift,
134447b0c7bSAndreas Larsson 				     int bits_per_word, int msb_first)
135447b0c7bSAndreas Larsson {
136447b0c7bSAndreas Larsson 	*rx_shift = 0;
137447b0c7bSAndreas Larsson 	*tx_shift = 0;
138447b0c7bSAndreas Larsson 	if (bits_per_word <= 16) {
139447b0c7bSAndreas Larsson 		if (msb_first) {
140447b0c7bSAndreas Larsson 			*rx_shift = 16; /* LSB in bit 16 */
141447b0c7bSAndreas Larsson 			*tx_shift = 32 - bits_per_word; /* MSB in bit 31 */
142447b0c7bSAndreas Larsson 		} else {
143447b0c7bSAndreas Larsson 			*rx_shift = 16 - bits_per_word; /* MSB in bit 15 */
144447b0c7bSAndreas Larsson 		}
145447b0c7bSAndreas Larsson 	}
146447b0c7bSAndreas Larsson }
147447b0c7bSAndreas Larsson 
mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs * cs,struct spi_device * spi,struct mpc8xxx_spi * mpc8xxx_spi,int bits_per_word)14899aebb3cSChristophe Leroy static void mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
149ca632f55SGrant Likely 				       struct spi_device *spi,
150ca632f55SGrant Likely 				       struct mpc8xxx_spi *mpc8xxx_spi,
151ca632f55SGrant Likely 				       int bits_per_word)
152ca632f55SGrant Likely {
153ca632f55SGrant Likely 	cs->rx_shift = 0;
154ca632f55SGrant Likely 	cs->tx_shift = 0;
155ca632f55SGrant Likely 	if (bits_per_word <= 8) {
156ca632f55SGrant Likely 		cs->get_rx = mpc8xxx_spi_rx_buf_u8;
157ca632f55SGrant Likely 		cs->get_tx = mpc8xxx_spi_tx_buf_u8;
158ca632f55SGrant Likely 	} else if (bits_per_word <= 16) {
159ca632f55SGrant Likely 		cs->get_rx = mpc8xxx_spi_rx_buf_u16;
160ca632f55SGrant Likely 		cs->get_tx = mpc8xxx_spi_tx_buf_u16;
161ca632f55SGrant Likely 	} else if (bits_per_word <= 32) {
162ca632f55SGrant Likely 		cs->get_rx = mpc8xxx_spi_rx_buf_u32;
163ca632f55SGrant Likely 		cs->get_tx = mpc8xxx_spi_tx_buf_u32;
16499aebb3cSChristophe Leroy 	}
165ca632f55SGrant Likely 
166b48c4e3cSAndreas Larsson 	if (mpc8xxx_spi->set_shifts)
167b48c4e3cSAndreas Larsson 		mpc8xxx_spi->set_shifts(&cs->rx_shift, &cs->tx_shift,
168b48c4e3cSAndreas Larsson 					bits_per_word,
169b48c4e3cSAndreas Larsson 					!(spi->mode & SPI_LSB_FIRST));
170b48c4e3cSAndreas Larsson 
171ca632f55SGrant Likely 	mpc8xxx_spi->rx_shift = cs->rx_shift;
172ca632f55SGrant Likely 	mpc8xxx_spi->tx_shift = cs->tx_shift;
173ca632f55SGrant Likely 	mpc8xxx_spi->get_rx = cs->get_rx;
174ca632f55SGrant Likely 	mpc8xxx_spi->get_tx = cs->get_tx;
175ca632f55SGrant Likely }
176ca632f55SGrant Likely 
fsl_spi_setup_transfer(struct spi_device * spi,struct spi_transfer * t)177ca632f55SGrant Likely static int fsl_spi_setup_transfer(struct spi_device *spi,
178ca632f55SGrant Likely 					struct spi_transfer *t)
179ca632f55SGrant Likely {
180ca632f55SGrant Likely 	struct mpc8xxx_spi *mpc8xxx_spi;
181ca632f55SGrant Likely 	int bits_per_word = 0;
182ca632f55SGrant Likely 	u8 pm;
183ca632f55SGrant Likely 	u32 hz = 0;
184ca632f55SGrant Likely 	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
185ca632f55SGrant Likely 
186*d32382caSYang Yingliang 	mpc8xxx_spi = spi_controller_get_devdata(spi->controller);
187ca632f55SGrant Likely 
188ca632f55SGrant Likely 	if (t) {
189ca632f55SGrant Likely 		bits_per_word = t->bits_per_word;
190ca632f55SGrant Likely 		hz = t->speed_hz;
191ca632f55SGrant Likely 	}
192ca632f55SGrant Likely 
193ca632f55SGrant Likely 	/* spi_transfer level calls that work per-word */
194ca632f55SGrant Likely 	if (!bits_per_word)
195ca632f55SGrant Likely 		bits_per_word = spi->bits_per_word;
196ca632f55SGrant Likely 
197ca632f55SGrant Likely 	if (!hz)
198ca632f55SGrant Likely 		hz = spi->max_speed_hz;
199ca632f55SGrant Likely 
200ca632f55SGrant Likely 	if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
20199aebb3cSChristophe Leroy 		mspi_apply_cpu_mode_quirks(cs, spi, mpc8xxx_spi, bits_per_word);
202ca632f55SGrant Likely 
203ca632f55SGrant Likely 	if (bits_per_word == 32)
204ca632f55SGrant Likely 		bits_per_word = 0;
205ca632f55SGrant Likely 	else
206ca632f55SGrant Likely 		bits_per_word = bits_per_word - 1;
207ca632f55SGrant Likely 
208ca632f55SGrant Likely 	/* mask out bits we are going to set */
209ca632f55SGrant Likely 	cs->hw_mode &= ~(SPMODE_LEN(0xF) | SPMODE_DIV16
210ca632f55SGrant Likely 				  | SPMODE_PM(0xF));
211ca632f55SGrant Likely 
212ca632f55SGrant Likely 	cs->hw_mode |= SPMODE_LEN(bits_per_word);
213ca632f55SGrant Likely 
214ca632f55SGrant Likely 	if ((mpc8xxx_spi->spibrg / hz) > 64) {
215ca632f55SGrant Likely 		cs->hw_mode |= SPMODE_DIV16;
216ca632f55SGrant Likely 		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
21731ae7794SMarkus Elfring 		WARN_ONCE(pm > 16,
21831ae7794SMarkus Elfring 			  "%s: Requested speed is too low: %d Hz. Will use %d Hz instead.\n",
21931ae7794SMarkus Elfring 			  dev_name(&spi->dev), hz, mpc8xxx_spi->spibrg / 1024);
220ca632f55SGrant Likely 		if (pm > 16)
221ca632f55SGrant Likely 			pm = 16;
222ca632f55SGrant Likely 	} else {
223ca632f55SGrant Likely 		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
224ca632f55SGrant Likely 	}
225ca632f55SGrant Likely 	if (pm)
226ca632f55SGrant Likely 		pm--;
227ca632f55SGrant Likely 
228ca632f55SGrant Likely 	cs->hw_mode |= SPMODE_PM(pm);
229ca632f55SGrant Likely 
230ca632f55SGrant Likely 	fsl_spi_change_mode(spi);
231ca632f55SGrant Likely 	return 0;
232ca632f55SGrant Likely }
233ca632f55SGrant Likely 
fsl_spi_cpu_bufs(struct mpc8xxx_spi * mspi,struct spi_transfer * t,unsigned int len)234ca632f55SGrant Likely static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
235ca632f55SGrant Likely 				struct spi_transfer *t, unsigned int len)
236ca632f55SGrant Likely {
237ca632f55SGrant Likely 	u32 word;
238dd67de8cSLuc Van Oostenryck 	struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
239ca632f55SGrant Likely 
240ca632f55SGrant Likely 	mspi->count = len;
241ca632f55SGrant Likely 
242ca632f55SGrant Likely 	/* enable rx ints */
243ca632f55SGrant Likely 	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
244ca632f55SGrant Likely 
245ca632f55SGrant Likely 	/* transmit word */
246ca632f55SGrant Likely 	word = mspi->get_tx(mspi);
247ca632f55SGrant Likely 	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
248ca632f55SGrant Likely 
249ca632f55SGrant Likely 	return 0;
250ca632f55SGrant Likely }
251ca632f55SGrant Likely 
fsl_spi_bufs(struct spi_device * spi,struct spi_transfer * t,bool is_dma_mapped)252ca632f55SGrant Likely static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
253ca632f55SGrant Likely 			    bool is_dma_mapped)
254ca632f55SGrant Likely {
255*d32382caSYang Yingliang 	struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(spi->controller);
256dd67de8cSLuc Van Oostenryck 	struct fsl_spi_reg __iomem *reg_base;
257ca632f55SGrant Likely 	unsigned int len = t->len;
258ca632f55SGrant Likely 	u8 bits_per_word;
259ca632f55SGrant Likely 	int ret;
260ca632f55SGrant Likely 
261ca632f55SGrant Likely 	reg_base = mpc8xxx_spi->reg_base;
262ca632f55SGrant Likely 	bits_per_word = spi->bits_per_word;
263ca632f55SGrant Likely 	if (t->bits_per_word)
264ca632f55SGrant Likely 		bits_per_word = t->bits_per_word;
265ca632f55SGrant Likely 
2664084c8caSChristophe Leroy 	if (bits_per_word > 8)
267ca632f55SGrant Likely 		len /= 2;
2684084c8caSChristophe Leroy 	if (bits_per_word > 16)
269ca632f55SGrant Likely 		len /= 2;
270ca632f55SGrant Likely 
271ca632f55SGrant Likely 	mpc8xxx_spi->tx = t->tx_buf;
272ca632f55SGrant Likely 	mpc8xxx_spi->rx = t->rx_buf;
273ca632f55SGrant Likely 
27416735d02SWolfram Sang 	reinit_completion(&mpc8xxx_spi->done);
275ca632f55SGrant Likely 
276ca632f55SGrant Likely 	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
277ca632f55SGrant Likely 		ret = fsl_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
278ca632f55SGrant Likely 	else
279ca632f55SGrant Likely 		ret = fsl_spi_cpu_bufs(mpc8xxx_spi, t, len);
280ca632f55SGrant Likely 	if (ret)
281ca632f55SGrant Likely 		return ret;
282ca632f55SGrant Likely 
283ca632f55SGrant Likely 	wait_for_completion(&mpc8xxx_spi->done);
284ca632f55SGrant Likely 
285ca632f55SGrant Likely 	/* disable rx ints */
286ca632f55SGrant Likely 	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
287ca632f55SGrant Likely 
288ca632f55SGrant Likely 	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
289ca632f55SGrant Likely 		fsl_spi_cpm_bufs_complete(mpc8xxx_spi);
290ca632f55SGrant Likely 
291ca632f55SGrant Likely 	return mpc8xxx_spi->count;
292ca632f55SGrant Likely }
293ca632f55SGrant Likely 
fsl_spi_prepare_message(struct spi_controller * ctlr,struct spi_message * m)29464ca1a03SChristophe Leroy static int fsl_spi_prepare_message(struct spi_controller *ctlr,
295c592becbSHeiner Kallweit 				   struct spi_message *m)
296ca632f55SGrant Likely {
29764ca1a03SChristophe Leroy 	struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(ctlr);
29864ca1a03SChristophe Leroy 	struct spi_transfer *t;
2993b553e00SChristophe Leroy 	struct spi_transfer *first;
3003b553e00SChristophe Leroy 
3013b553e00SChristophe Leroy 	first = list_first_entry(&m->transfers, struct spi_transfer,
3023b553e00SChristophe Leroy 				 transfer_list);
303ca632f55SGrant Likely 
304af0e6242SRasmus Villemoes 	/*
305af0e6242SRasmus Villemoes 	 * In CPU mode, optimize large byte transfers to use larger
306af0e6242SRasmus Villemoes 	 * bits_per_word values to reduce number of interrupts taken.
3073b553e00SChristophe Leroy 	 *
3083b553e00SChristophe Leroy 	 * Some glitches can appear on the SPI clock when the mode changes.
3093b553e00SChristophe Leroy 	 * Check that there is no speed change during the transfer and set it up
3103b553e00SChristophe Leroy 	 * now to change the mode without having a chip-select asserted.
311af0e6242SRasmus Villemoes 	 */
312af0e6242SRasmus Villemoes 	list_for_each_entry(t, &m->transfers, transfer_list) {
3133b553e00SChristophe Leroy 		if (t->speed_hz != first->speed_hz) {
3143b553e00SChristophe Leroy 			dev_err(&m->spi->dev,
3153b553e00SChristophe Leroy 				"speed_hz cannot change during message.\n");
3163b553e00SChristophe Leroy 			return -EINVAL;
3173b553e00SChristophe Leroy 		}
3183b553e00SChristophe Leroy 		if (!(mpc8xxx_spi->flags & SPI_CPM_MODE)) {
319af0e6242SRasmus Villemoes 			if (t->len < 256 || t->bits_per_word != 8)
320af0e6242SRasmus Villemoes 				continue;
321af0e6242SRasmus Villemoes 			if ((t->len & 3) == 0)
322af0e6242SRasmus Villemoes 				t->bits_per_word = 32;
323af0e6242SRasmus Villemoes 			else if ((t->len & 1) == 0)
324af0e6242SRasmus Villemoes 				t->bits_per_word = 16;
3258a5299a1SChristophe Leroy 		} else {
3268a5299a1SChristophe Leroy 			/*
3278a5299a1SChristophe Leroy 			 * CPM/QE uses Little Endian for words > 8
3288a5299a1SChristophe Leroy 			 * so transform 16 and 32 bits words into 8 bits
3298a5299a1SChristophe Leroy 			 * Unfortnatly that doesn't work for LSB so
3308a5299a1SChristophe Leroy 			 * reject these for now
3318a5299a1SChristophe Leroy 			 * Note: 32 bits word, LSB works iff
3328a5299a1SChristophe Leroy 			 * tfcr/rfcr is set to CPMFCR_GBL
3338a5299a1SChristophe Leroy 			 */
3348a5299a1SChristophe Leroy 			if (m->spi->mode & SPI_LSB_FIRST && t->bits_per_word > 8)
3358a5299a1SChristophe Leroy 				return -EINVAL;
3368a5299a1SChristophe Leroy 			if (t->bits_per_word == 16 || t->bits_per_word == 32)
3378a5299a1SChristophe Leroy 				t->bits_per_word = 8; /* pretend its 8 bits */
338fc96ec82SChristophe Leroy 			if (t->bits_per_word == 8 && t->len >= 256 &&
339fc96ec82SChristophe Leroy 			    (mpc8xxx_spi->flags & SPI_CPM1))
340fc96ec82SChristophe Leroy 				t->bits_per_word = 16;
341af0e6242SRasmus Villemoes 		}
342af0e6242SRasmus Villemoes 	}
3433b553e00SChristophe Leroy 	return fsl_spi_setup_transfer(m->spi, first);
3444302a596SStefan Roese }
3454302a596SStefan Roese 
fsl_spi_transfer_one(struct spi_controller * controller,struct spi_device * spi,struct spi_transfer * t)34664ca1a03SChristophe Leroy static int fsl_spi_transfer_one(struct spi_controller *controller,
34764ca1a03SChristophe Leroy 				struct spi_device *spi,
34864ca1a03SChristophe Leroy 				struct spi_transfer *t)
34964ca1a03SChristophe Leroy {
35064ca1a03SChristophe Leroy 	int status;
35164ca1a03SChristophe Leroy 
352ca632f55SGrant Likely 	status = fsl_spi_setup_transfer(spi, t);
353ca632f55SGrant Likely 	if (status < 0)
35464ca1a03SChristophe Leroy 		return status;
355ca632f55SGrant Likely 	if (t->len)
35664ca1a03SChristophe Leroy 		status = fsl_spi_bufs(spi, t, !!t->tx_dma || !!t->rx_dma);
35764ca1a03SChristophe Leroy 	if (status > 0)
35864ca1a03SChristophe Leroy 		return -EMSGSIZE;
359ca632f55SGrant Likely 
36064ca1a03SChristophe Leroy 	return status;
361ca632f55SGrant Likely }
362ca632f55SGrant Likely 
fsl_spi_unprepare_message(struct spi_controller * controller,struct spi_message * msg)36364ca1a03SChristophe Leroy static int fsl_spi_unprepare_message(struct spi_controller *controller,
36464ca1a03SChristophe Leroy 				     struct spi_message *msg)
36564ca1a03SChristophe Leroy {
36664ca1a03SChristophe Leroy 	return fsl_spi_setup_transfer(msg->spi, NULL);
367ca632f55SGrant Likely }
368ca632f55SGrant Likely 
fsl_spi_setup(struct spi_device * spi)369ca632f55SGrant Likely static int fsl_spi_setup(struct spi_device *spi)
370ca632f55SGrant Likely {
371ca632f55SGrant Likely 	struct mpc8xxx_spi *mpc8xxx_spi;
372dd67de8cSLuc Van Oostenryck 	struct fsl_spi_reg __iomem *reg_base;
3732ec6f20bSLukas Wunner 	bool initial_setup = false;
374ca632f55SGrant Likely 	int retval;
375ca632f55SGrant Likely 	u32 hw_mode;
376d9f26748SAxel Lin 	struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi);
377ca632f55SGrant Likely 
378ca632f55SGrant Likely 	if (!spi->max_speed_hz)
379ca632f55SGrant Likely 		return -EINVAL;
380ca632f55SGrant Likely 
381ca632f55SGrant Likely 	if (!cs) {
382d9f26748SAxel Lin 		cs = kzalloc(sizeof(*cs), GFP_KERNEL);
383ca632f55SGrant Likely 		if (!cs)
384ca632f55SGrant Likely 			return -ENOMEM;
385d9f26748SAxel Lin 		spi_set_ctldata(spi, cs);
3862ec6f20bSLukas Wunner 		initial_setup = true;
387ca632f55SGrant Likely 	}
388*d32382caSYang Yingliang 	mpc8xxx_spi = spi_controller_get_devdata(spi->controller);
389ca632f55SGrant Likely 
390ca632f55SGrant Likely 	reg_base = mpc8xxx_spi->reg_base;
391ca632f55SGrant Likely 
392ca632f55SGrant Likely 	hw_mode = cs->hw_mode; /* Save original settings */
393ca632f55SGrant Likely 	cs->hw_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
394ca632f55SGrant Likely 	/* mask out bits we are going to set */
395ca632f55SGrant Likely 	cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
396ca632f55SGrant Likely 			 | SPMODE_REV | SPMODE_LOOP);
397ca632f55SGrant Likely 
398ca632f55SGrant Likely 	if (spi->mode & SPI_CPHA)
399ca632f55SGrant Likely 		cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK;
400ca632f55SGrant Likely 	if (spi->mode & SPI_CPOL)
401ca632f55SGrant Likely 		cs->hw_mode |= SPMODE_CI_INACTIVEHIGH;
402ca632f55SGrant Likely 	if (!(spi->mode & SPI_LSB_FIRST))
403ca632f55SGrant Likely 		cs->hw_mode |= SPMODE_REV;
404ca632f55SGrant Likely 	if (spi->mode & SPI_LOOP)
405ca632f55SGrant Likely 		cs->hw_mode |= SPMODE_LOOP;
406ca632f55SGrant Likely 
407ca632f55SGrant Likely 	retval = fsl_spi_setup_transfer(spi, NULL);
408ca632f55SGrant Likely 	if (retval < 0) {
409ca632f55SGrant Likely 		cs->hw_mode = hw_mode; /* Restore settings */
4102ec6f20bSLukas Wunner 		if (initial_setup)
4112ec6f20bSLukas Wunner 			kfree(cs);
412ca632f55SGrant Likely 		return retval;
413ca632f55SGrant Likely 	}
414f482cd0fSAndreas Larsson 
415ca632f55SGrant Likely 	return 0;
416ca632f55SGrant Likely }
417ca632f55SGrant Likely 
fsl_spi_cleanup(struct spi_device * spi)41876a7498fSAndreas Larsson static void fsl_spi_cleanup(struct spi_device *spi)
41976a7498fSAndreas Larsson {
420d9f26748SAxel Lin 	struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi);
42176a7498fSAndreas Larsson 
422d9f26748SAxel Lin 	kfree(cs);
423d9f26748SAxel Lin 	spi_set_ctldata(spi, NULL);
42476a7498fSAndreas Larsson }
42576a7498fSAndreas Larsson 
fsl_spi_cpu_irq(struct mpc8xxx_spi * mspi,u32 events)426ca632f55SGrant Likely static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
427ca632f55SGrant Likely {
428dd67de8cSLuc Van Oostenryck 	struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
429ca632f55SGrant Likely 
430ca632f55SGrant Likely 	/* We need handle RX first */
431ca632f55SGrant Likely 	if (events & SPIE_NE) {
432ca632f55SGrant Likely 		u32 rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
433ca632f55SGrant Likely 
434ca632f55SGrant Likely 		if (mspi->rx)
435ca632f55SGrant Likely 			mspi->get_rx(rx_data, mspi);
436ca632f55SGrant Likely 	}
437ca632f55SGrant Likely 
438ca632f55SGrant Likely 	if ((events & SPIE_NF) == 0)
439ca632f55SGrant Likely 		/* spin until TX is done */
440ca632f55SGrant Likely 		while (((events =
441ca632f55SGrant Likely 			mpc8xxx_spi_read_reg(&reg_base->event)) &
442ca632f55SGrant Likely 						SPIE_NF) == 0)
443ca632f55SGrant Likely 			cpu_relax();
444ca632f55SGrant Likely 
445ca632f55SGrant Likely 	/* Clear the events */
446ca632f55SGrant Likely 	mpc8xxx_spi_write_reg(&reg_base->event, events);
447ca632f55SGrant Likely 
448ca632f55SGrant Likely 	mspi->count -= 1;
449ca632f55SGrant Likely 	if (mspi->count) {
450ca632f55SGrant Likely 		u32 word = mspi->get_tx(mspi);
451ca632f55SGrant Likely 
452ca632f55SGrant Likely 		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
453ca632f55SGrant Likely 	} else {
454ca632f55SGrant Likely 		complete(&mspi->done);
455ca632f55SGrant Likely 	}
456ca632f55SGrant Likely }
457ca632f55SGrant Likely 
fsl_spi_irq(s32 irq,void * context_data)458ca632f55SGrant Likely static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
459ca632f55SGrant Likely {
460ca632f55SGrant Likely 	struct mpc8xxx_spi *mspi = context_data;
461ca632f55SGrant Likely 	irqreturn_t ret = IRQ_NONE;
462ca632f55SGrant Likely 	u32 events;
463dd67de8cSLuc Van Oostenryck 	struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
464ca632f55SGrant Likely 
465ca632f55SGrant Likely 	/* Get interrupt events(tx/rx) */
466ca632f55SGrant Likely 	events = mpc8xxx_spi_read_reg(&reg_base->event);
467ca632f55SGrant Likely 	if (events)
468ca632f55SGrant Likely 		ret = IRQ_HANDLED;
469ca632f55SGrant Likely 
470ca632f55SGrant Likely 	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
471ca632f55SGrant Likely 
472ca632f55SGrant Likely 	if (mspi->flags & SPI_CPM_MODE)
473ca632f55SGrant Likely 		fsl_spi_cpm_irq(mspi, events);
474ca632f55SGrant Likely 	else
475ca632f55SGrant Likely 		fsl_spi_cpu_irq(mspi, events);
476ca632f55SGrant Likely 
477ca632f55SGrant Likely 	return ret;
478ca632f55SGrant Likely }
479ca632f55SGrant Likely 
fsl_spi_grlib_cs_control(struct spi_device * spi,bool on)480447b0c7bSAndreas Larsson static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
481447b0c7bSAndreas Larsson {
482*d32382caSYang Yingliang 	struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(spi->controller);
483dd67de8cSLuc Van Oostenryck 	struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
484447b0c7bSAndreas Larsson 	u32 slvsel;
4859e264f3fSAmit Kumar Mahapatra via Alsa-devel 	u16 cs = spi_get_chipselect(spi, 0);
486447b0c7bSAndreas Larsson 
48764ca1a03SChristophe Leroy 	if (cs < mpc8xxx_spi->native_chipselects) {
488447b0c7bSAndreas Larsson 		slvsel = mpc8xxx_spi_read_reg(&reg_base->slvsel);
489447b0c7bSAndreas Larsson 		slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs));
490447b0c7bSAndreas Larsson 		mpc8xxx_spi_write_reg(&reg_base->slvsel, slvsel);
491447b0c7bSAndreas Larsson 	}
49276a7498fSAndreas Larsson }
493447b0c7bSAndreas Larsson 
fsl_spi_grlib_probe(struct device * dev)494447b0c7bSAndreas Larsson static void fsl_spi_grlib_probe(struct device *dev)
495447b0c7bSAndreas Larsson {
496*d32382caSYang Yingliang 	struct spi_controller *host = dev_get_drvdata(dev);
497*d32382caSYang Yingliang 	struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host);
498dd67de8cSLuc Van Oostenryck 	struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
499447b0c7bSAndreas Larsson 	int mbits;
500447b0c7bSAndreas Larsson 	u32 capabilities;
501447b0c7bSAndreas Larsson 
502447b0c7bSAndreas Larsson 	capabilities = mpc8xxx_spi_read_reg(&reg_base->cap);
503447b0c7bSAndreas Larsson 
504447b0c7bSAndreas Larsson 	mpc8xxx_spi->set_shifts = fsl_spi_grlib_set_shifts;
505447b0c7bSAndreas Larsson 	mbits = SPCAP_MAXWLEN(capabilities);
506447b0c7bSAndreas Larsson 	if (mbits)
507447b0c7bSAndreas Larsson 		mpc8xxx_spi->max_bits_per_word = mbits + 1;
508447b0c7bSAndreas Larsson 
50976a7498fSAndreas Larsson 	mpc8xxx_spi->native_chipselects = 0;
510447b0c7bSAndreas Larsson 	if (SPCAP_SSEN(capabilities)) {
51176a7498fSAndreas Larsson 		mpc8xxx_spi->native_chipselects = SPCAP_SSSZ(capabilities);
512447b0c7bSAndreas Larsson 		mpc8xxx_spi_write_reg(&reg_base->slvsel, 0xffffffff);
513447b0c7bSAndreas Larsson 	}
514*d32382caSYang Yingliang 	host->num_chipselect = mpc8xxx_spi->native_chipselects;
515*d32382caSYang Yingliang 	host->set_cs = fsl_spi_grlib_cs_control;
51664ca1a03SChristophe Leroy }
51764ca1a03SChristophe Leroy 
fsl_spi_cs_control(struct spi_device * spi,bool on)51864ca1a03SChristophe Leroy static void fsl_spi_cs_control(struct spi_device *spi, bool on)
51964ca1a03SChristophe Leroy {
52064ca1a03SChristophe Leroy 	struct device *dev = spi->dev.parent->parent;
52164ca1a03SChristophe Leroy 	struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
52264ca1a03SChristophe Leroy 	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
52364ca1a03SChristophe Leroy 
52464ca1a03SChristophe Leroy 	if (WARN_ON_ONCE(!pinfo->immr_spi_cs))
52564ca1a03SChristophe Leroy 		return;
52664ca1a03SChristophe Leroy 	iowrite32be(on ? 0 : SPI_BOOT_SEL_BIT, pinfo->immr_spi_cs);
527447b0c7bSAndreas Larsson }
528447b0c7bSAndreas Larsson 
fsl_spi_probe(struct device * dev,struct resource * mem,unsigned int irq)529*d32382caSYang Yingliang static struct spi_controller *fsl_spi_probe(struct device *dev,
530ca632f55SGrant Likely 		struct resource *mem, unsigned int irq)
531ca632f55SGrant Likely {
5328074cf06SJingoo Han 	struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
533*d32382caSYang Yingliang 	struct spi_controller *host;
534ca632f55SGrant Likely 	struct mpc8xxx_spi *mpc8xxx_spi;
535dd67de8cSLuc Van Oostenryck 	struct fsl_spi_reg __iomem *reg_base;
536ca632f55SGrant Likely 	u32 regval;
537ca632f55SGrant Likely 	int ret = 0;
538ca632f55SGrant Likely 
539*d32382caSYang Yingliang 	host = spi_alloc_host(dev, sizeof(struct mpc8xxx_spi));
540*d32382caSYang Yingliang 	if (host == NULL) {
541ca632f55SGrant Likely 		ret = -ENOMEM;
542ca632f55SGrant Likely 		goto err;
543ca632f55SGrant Likely 	}
544ca632f55SGrant Likely 
545*d32382caSYang Yingliang 	dev_set_drvdata(dev, host);
546ca632f55SGrant Likely 
547c592becbSHeiner Kallweit 	mpc8xxx_spi_probe(dev, mem, irq);
548ca632f55SGrant Likely 
549*d32382caSYang Yingliang 	host->setup = fsl_spi_setup;
550*d32382caSYang Yingliang 	host->cleanup = fsl_spi_cleanup;
551*d32382caSYang Yingliang 	host->prepare_message = fsl_spi_prepare_message;
552*d32382caSYang Yingliang 	host->transfer_one = fsl_spi_transfer_one;
553*d32382caSYang Yingliang 	host->unprepare_message = fsl_spi_unprepare_message;
554*d32382caSYang Yingliang 	host->use_gpio_descriptors = true;
555*d32382caSYang Yingliang 	host->set_cs = fsl_spi_cs_control;
556ca632f55SGrant Likely 
557*d32382caSYang Yingliang 	mpc8xxx_spi = spi_controller_get_devdata(host);
5588922a366SAndreas Larsson 	mpc8xxx_spi->max_bits_per_word = 32;
559c3f3e771SAndreas Larsson 	mpc8xxx_spi->type = fsl_spi_get_type(dev);
560ca632f55SGrant Likely 
561ca632f55SGrant Likely 	ret = fsl_spi_cpm_init(mpc8xxx_spi);
562ca632f55SGrant Likely 	if (ret)
563ca632f55SGrant Likely 		goto err_cpm_init;
564ca632f55SGrant Likely 
5654178b6b1SHeiner Kallweit 	mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem);
56637c5db79SAxel Lin 	if (IS_ERR(mpc8xxx_spi->reg_base)) {
56737c5db79SAxel Lin 		ret = PTR_ERR(mpc8xxx_spi->reg_base);
5684178b6b1SHeiner Kallweit 		goto err_probe;
569447b0c7bSAndreas Larsson 	}
570447b0c7bSAndreas Larsson 
571447b0c7bSAndreas Larsson 	if (mpc8xxx_spi->type == TYPE_GRLIB)
572447b0c7bSAndreas Larsson 		fsl_spi_grlib_probe(dev);
573447b0c7bSAndreas Larsson 
5748a5299a1SChristophe Leroy 	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
575*d32382caSYang Yingliang 		host->bits_per_word_mask =
5768a5299a1SChristophe Leroy 			(SPI_BPW_RANGE_MASK(4, 8) | SPI_BPW_MASK(16) | SPI_BPW_MASK(32));
5778a5299a1SChristophe Leroy 	else
578*d32382caSYang Yingliang 		host->bits_per_word_mask =
5798a5299a1SChristophe Leroy 			(SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32));
5808a5299a1SChristophe Leroy 
581*d32382caSYang Yingliang 	host->bits_per_word_mask &=
582f734394dSAxel Lin 		SPI_BPW_RANGE_MASK(1, mpc8xxx_spi->max_bits_per_word);
583f734394dSAxel Lin 
584b48c4e3cSAndreas Larsson 	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
585b48c4e3cSAndreas Larsson 		mpc8xxx_spi->set_shifts = fsl_spi_qe_cpu_set_shifts;
586b48c4e3cSAndreas Larsson 
587b48c4e3cSAndreas Larsson 	if (mpc8xxx_spi->set_shifts)
588b48c4e3cSAndreas Larsson 		/* 8 bits per word and MSB first */
589b48c4e3cSAndreas Larsson 		mpc8xxx_spi->set_shifts(&mpc8xxx_spi->rx_shift,
590b48c4e3cSAndreas Larsson 					&mpc8xxx_spi->tx_shift, 8, 1);
591ca632f55SGrant Likely 
592ca632f55SGrant Likely 	/* Register for SPI Interrupt */
5934178b6b1SHeiner Kallweit 	ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_spi_irq,
594ca632f55SGrant Likely 			       0, "fsl_spi", mpc8xxx_spi);
595ca632f55SGrant Likely 
596ca632f55SGrant Likely 	if (ret != 0)
5974178b6b1SHeiner Kallweit 		goto err_probe;
598ca632f55SGrant Likely 
599ca632f55SGrant Likely 	reg_base = mpc8xxx_spi->reg_base;
600ca632f55SGrant Likely 
601ca632f55SGrant Likely 	/* SPI controller initializations */
602ca632f55SGrant Likely 	mpc8xxx_spi_write_reg(&reg_base->mode, 0);
603ca632f55SGrant Likely 	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
604ca632f55SGrant Likely 	mpc8xxx_spi_write_reg(&reg_base->command, 0);
605ca632f55SGrant Likely 	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
606ca632f55SGrant Likely 
607ca632f55SGrant Likely 	/* Enable SPI interface */
608ca632f55SGrant Likely 	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
6098922a366SAndreas Larsson 	if (mpc8xxx_spi->max_bits_per_word < 8) {
6108922a366SAndreas Larsson 		regval &= ~SPMODE_LEN(0xF);
6118922a366SAndreas Larsson 		regval |= SPMODE_LEN(mpc8xxx_spi->max_bits_per_word - 1);
6128922a366SAndreas Larsson 	}
613ca632f55SGrant Likely 	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
614ca632f55SGrant Likely 		regval |= SPMODE_OP;
615ca632f55SGrant Likely 
616ca632f55SGrant Likely 	mpc8xxx_spi_write_reg(&reg_base->mode, regval);
617ca632f55SGrant Likely 
618*d32382caSYang Yingliang 	ret = devm_spi_register_controller(dev, host);
619ca632f55SGrant Likely 	if (ret < 0)
6204178b6b1SHeiner Kallweit 		goto err_probe;
621ca632f55SGrant Likely 
622ca632f55SGrant Likely 	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
623ca632f55SGrant Likely 		 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
624ca632f55SGrant Likely 
625*d32382caSYang Yingliang 	return host;
626ca632f55SGrant Likely 
6274178b6b1SHeiner Kallweit err_probe:
628ca632f55SGrant Likely 	fsl_spi_cpm_free(mpc8xxx_spi);
629ca632f55SGrant Likely err_cpm_init:
630*d32382caSYang Yingliang 	spi_controller_put(host);
631ca632f55SGrant Likely err:
632ca632f55SGrant Likely 	return ERR_PTR(ret);
633ca632f55SGrant Likely }
634ca632f55SGrant Likely 
of_fsl_spi_probe(struct platform_device * ofdev)635fd4a319bSGrant Likely static int of_fsl_spi_probe(struct platform_device *ofdev)
636ca632f55SGrant Likely {
637ca632f55SGrant Likely 	struct device *dev = &ofdev->dev;
638ca632f55SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
639*d32382caSYang Yingliang 	struct spi_controller *host;
640ca632f55SGrant Likely 	struct resource mem;
6412f3d8035SChristophe Leroy 	int irq, type;
6422f3d8035SChristophe Leroy 	int ret;
6435fed9fe5SYang Yingliang 	bool spisel_boot = false;
6445fed9fe5SYang Yingliang #if IS_ENABLED(CONFIG_FSL_SOC)
6455fed9fe5SYang Yingliang 	struct mpc8xxx_spi_probe_info *pinfo = NULL;
6465fed9fe5SYang Yingliang #endif
6475fed9fe5SYang Yingliang 
648ca632f55SGrant Likely 
649ca632f55SGrant Likely 	ret = of_mpc8xxx_spi_probe(ofdev);
650ca632f55SGrant Likely 	if (ret)
651ca632f55SGrant Likely 		return ret;
652ca632f55SGrant Likely 
653447b0c7bSAndreas Larsson 	type = fsl_spi_get_type(&ofdev->dev);
654447b0c7bSAndreas Larsson 	if (type == TYPE_FSL) {
6550f0581b2SLinus Walleij 		struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
6560f0581b2SLinus Walleij #if IS_ENABLED(CONFIG_FSL_SOC)
6575fed9fe5SYang Yingliang 		pinfo = to_of_pinfo(pdata);
6580f0581b2SLinus Walleij 
659122541f2SRasmus Villemoes 		spisel_boot = of_property_read_bool(np, "fsl,spisel_boot");
6600f0581b2SLinus Walleij 		if (spisel_boot) {
6610f0581b2SLinus Walleij 			pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4);
6622f3d8035SChristophe Leroy 			if (!pinfo->immr_spi_cs)
6632f3d8035SChristophe Leroy 				return -ENOMEM;
6640f0581b2SLinus Walleij 		}
6650f0581b2SLinus Walleij #endif
6667251953dSLinus Walleij 		/*
6677251953dSLinus Walleij 		 * Handle the case where we have one hardwired (always selected)
6687251953dSLinus Walleij 		 * device on the first "chipselect". Else we let the core code
6697251953dSLinus Walleij 		 * handle any GPIOs or native chip selects and assign the
6707251953dSLinus Walleij 		 * appropriate callback for dealing with the CS lines. This isn't
6717251953dSLinus Walleij 		 * supported on the GRLIB variant.
6727251953dSLinus Walleij 		 */
6737251953dSLinus Walleij 		ret = gpiod_count(dev, "cs");
674122541f2SRasmus Villemoes 		if (ret < 0)
675122541f2SRasmus Villemoes 			ret = 0;
67664ca1a03SChristophe Leroy 		if (ret == 0 && !spisel_boot)
6777251953dSLinus Walleij 			pdata->max_chipselect = 1;
67864ca1a03SChristophe Leroy 		else
679122541f2SRasmus Villemoes 			pdata->max_chipselect = ret + spisel_boot;
680122541f2SRasmus Villemoes 	}
681ca632f55SGrant Likely 
682ca632f55SGrant Likely 	ret = of_address_to_resource(np, 0, &mem);
683ca632f55SGrant Likely 	if (ret)
6845fed9fe5SYang Yingliang 		goto unmap_out;
685ca632f55SGrant Likely 
68663aa6a69SChristophe Leroy 	irq = platform_get_irq(ofdev, 0);
6875fed9fe5SYang Yingliang 	if (irq < 0) {
6885fed9fe5SYang Yingliang 		ret = irq;
6895fed9fe5SYang Yingliang 		goto unmap_out;
6905fed9fe5SYang Yingliang 	}
691ca632f55SGrant Likely 
692*d32382caSYang Yingliang 	host = fsl_spi_probe(dev, &mem, irq);
693ca632f55SGrant Likely 
694*d32382caSYang Yingliang 	return PTR_ERR_OR_ZERO(host);
6955fed9fe5SYang Yingliang 
6965fed9fe5SYang Yingliang unmap_out:
6975fed9fe5SYang Yingliang #if IS_ENABLED(CONFIG_FSL_SOC)
6985fed9fe5SYang Yingliang 	if (spisel_boot)
6995fed9fe5SYang Yingliang 		iounmap(pinfo->immr_spi_cs);
7005fed9fe5SYang Yingliang #endif
7015fed9fe5SYang Yingliang 	return ret;
702ca632f55SGrant Likely }
703ca632f55SGrant Likely 
of_fsl_spi_remove(struct platform_device * ofdev)704fc4935a0SUwe Kleine-König static void of_fsl_spi_remove(struct platform_device *ofdev)
705ca632f55SGrant Likely {
706*d32382caSYang Yingliang 	struct spi_controller *host = platform_get_drvdata(ofdev);
707*d32382caSYang Yingliang 	struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host);
708ca632f55SGrant Likely 
7093c5395b6SHeiner Kallweit 	fsl_spi_cpm_free(mpc8xxx_spi);
710ca632f55SGrant Likely }
711ca632f55SGrant Likely 
712ca632f55SGrant Likely static struct platform_driver of_fsl_spi_driver = {
713ca632f55SGrant Likely 	.driver = {
714ca632f55SGrant Likely 		.name = "fsl_spi",
715ca632f55SGrant Likely 		.of_match_table = of_fsl_spi_match,
716ca632f55SGrant Likely 	},
717ca632f55SGrant Likely 	.probe		= of_fsl_spi_probe,
718fc4935a0SUwe Kleine-König 	.remove_new	= of_fsl_spi_remove,
719ca632f55SGrant Likely };
720ca632f55SGrant Likely 
721ca632f55SGrant Likely #ifdef CONFIG_MPC832x_RDB
722ca632f55SGrant Likely /*
723ca632f55SGrant Likely  * XXX XXX XXX
724ca632f55SGrant Likely  * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
725ca632f55SGrant Likely  * only. The driver should go away soon, since newer MPC8323E-RDB's device
726ca632f55SGrant Likely  * tree can work with OpenFirmware driver. But for now we support old trees
727ca632f55SGrant Likely  * as well.
728ca632f55SGrant Likely  */
plat_mpc8xxx_spi_probe(struct platform_device * pdev)729fd4a319bSGrant Likely static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
730ca632f55SGrant Likely {
731ca632f55SGrant Likely 	struct resource *mem;
732ca632f55SGrant Likely 	int irq;
733*d32382caSYang Yingliang 	struct spi_controller *host;
734ca632f55SGrant Likely 
7358074cf06SJingoo Han 	if (!dev_get_platdata(&pdev->dev))
736ca632f55SGrant Likely 		return -EINVAL;
737ca632f55SGrant Likely 
738ca632f55SGrant Likely 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
739ca632f55SGrant Likely 	if (!mem)
740ca632f55SGrant Likely 		return -EINVAL;
741ca632f55SGrant Likely 
742ca632f55SGrant Likely 	irq = platform_get_irq(pdev, 0);
743d8736266SZhu Wang 	if (irq < 0)
744d8736266SZhu Wang 		return irq;
745ca632f55SGrant Likely 
746*d32382caSYang Yingliang 	host = fsl_spi_probe(&pdev->dev, mem, irq);
747*d32382caSYang Yingliang 	return PTR_ERR_OR_ZERO(host);
748ca632f55SGrant Likely }
749ca632f55SGrant Likely 
plat_mpc8xxx_spi_remove(struct platform_device * pdev)750fc4935a0SUwe Kleine-König static void plat_mpc8xxx_spi_remove(struct platform_device *pdev)
751ca632f55SGrant Likely {
752*d32382caSYang Yingliang 	struct spi_controller *host = platform_get_drvdata(pdev);
753*d32382caSYang Yingliang 	struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host);
7543c5395b6SHeiner Kallweit 
7553c5395b6SHeiner Kallweit 	fsl_spi_cpm_free(mpc8xxx_spi);
756ca632f55SGrant Likely }
757ca632f55SGrant Likely 
758ca632f55SGrant Likely MODULE_ALIAS("platform:mpc8xxx_spi");
759ca632f55SGrant Likely static struct platform_driver mpc8xxx_spi_driver = {
760ca632f55SGrant Likely 	.probe = plat_mpc8xxx_spi_probe,
761fc4935a0SUwe Kleine-König 	.remove_new = plat_mpc8xxx_spi_remove,
762ca632f55SGrant Likely 	.driver = {
763ca632f55SGrant Likely 		.name = "mpc8xxx_spi",
764ca632f55SGrant Likely 	},
765ca632f55SGrant Likely };
766ca632f55SGrant Likely 
767ca632f55SGrant Likely static bool legacy_driver_failed;
768ca632f55SGrant Likely 
legacy_driver_register(void)769ca632f55SGrant Likely static void __init legacy_driver_register(void)
770ca632f55SGrant Likely {
771ca632f55SGrant Likely 	legacy_driver_failed = platform_driver_register(&mpc8xxx_spi_driver);
772ca632f55SGrant Likely }
773ca632f55SGrant Likely 
legacy_driver_unregister(void)774ca632f55SGrant Likely static void __exit legacy_driver_unregister(void)
775ca632f55SGrant Likely {
776ca632f55SGrant Likely 	if (legacy_driver_failed)
777ca632f55SGrant Likely 		return;
778ca632f55SGrant Likely 	platform_driver_unregister(&mpc8xxx_spi_driver);
779ca632f55SGrant Likely }
780ca632f55SGrant Likely #else
legacy_driver_register(void)781ca632f55SGrant Likely static void __init legacy_driver_register(void) {}
legacy_driver_unregister(void)782ca632f55SGrant Likely static void __exit legacy_driver_unregister(void) {}
783ca632f55SGrant Likely #endif /* CONFIG_MPC832x_RDB */
784ca632f55SGrant Likely 
fsl_spi_init(void)785ca632f55SGrant Likely static int __init fsl_spi_init(void)
786ca632f55SGrant Likely {
787ca632f55SGrant Likely 	legacy_driver_register();
788ca632f55SGrant Likely 	return platform_driver_register(&of_fsl_spi_driver);
789ca632f55SGrant Likely }
790ca632f55SGrant Likely module_init(fsl_spi_init);
791ca632f55SGrant Likely 
fsl_spi_exit(void)792ca632f55SGrant Likely static void __exit fsl_spi_exit(void)
793ca632f55SGrant Likely {
794ca632f55SGrant Likely 	platform_driver_unregister(&of_fsl_spi_driver);
795ca632f55SGrant Likely 	legacy_driver_unregister();
796ca632f55SGrant Likely }
797ca632f55SGrant Likely module_exit(fsl_spi_exit);
798ca632f55SGrant Likely 
799ca632f55SGrant Likely MODULE_AUTHOR("Kumar Gala");
800ca632f55SGrant Likely MODULE_DESCRIPTION("Simple Freescale SPI Driver");
801ca632f55SGrant Likely MODULE_LICENSE("GPL");
802