[go: nahoru, domu]

1ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala/*
2b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu * Freescale SPI controller driver.
3ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala *
4ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala * Maintainer: Kumar Gala
5ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala *
6ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala * Copyright (C) 2006 Polycom, Inc.
7b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu * Copyright 2010 Freescale Semiconductor, Inc.
8ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala *
94c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov * CPM SPI and QE buffer descriptors mode support:
104c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov * Copyright (c) 2009  MontaVista Software, Inc.
114c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
124c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov *
13447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson * GRLIB support:
14447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson * Copyright (c) 2012 Aeroflex Gaisler AB.
15447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson * Author: Andreas Larsson <andreas@gaisler.com>
16447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson *
17ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala * This program is free software; you can redistribute  it and/or modify it
18ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala * under  the terms of  the GNU General  Public License as published by the
19ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala * Free Software Foundation;  either version 2 of the  License, or (at your
20ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala * option) any later version.
21ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala */
22ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala#include <linux/delay.h>
234c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov#include <linux/dma-mapping.h>
24a31083600476ac11b656bbc70784767f231469ffXiubo Li#include <linux/fsl_devices.h>
25a31083600476ac11b656bbc70784767f231469ffXiubo Li#include <linux/gpio.h>
26a31083600476ac11b656bbc70784767f231469ffXiubo Li#include <linux/interrupt.h>
27a31083600476ac11b656bbc70784767f231469ffXiubo Li#include <linux/irq.h>
28a31083600476ac11b656bbc70784767f231469ffXiubo Li#include <linux/kernel.h>
294c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov#include <linux/mm.h>
30a31083600476ac11b656bbc70784767f231469ffXiubo Li#include <linux/module.h>
314c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov#include <linux/mutex.h>
3235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov#include <linux/of.h>
33e8beacbb85a5c1de1117400c5ddb450514a8372cAndreas Larsson#include <linux/of_address.h>
34e8beacbb85a5c1de1117400c5ddb450514a8372cAndreas Larsson#include <linux/of_irq.h>
3535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov#include <linux/of_gpio.h>
36a31083600476ac11b656bbc70784767f231469ffXiubo Li#include <linux/of_platform.h>
37a31083600476ac11b656bbc70784767f231469ffXiubo Li#include <linux/platform_device.h>
38a31083600476ac11b656bbc70784767f231469ffXiubo Li#include <linux/spi/spi.h>
39a31083600476ac11b656bbc70784767f231469ffXiubo Li#include <linux/spi/spi_bitbang.h>
40a31083600476ac11b656bbc70784767f231469ffXiubo Li#include <linux/types.h>
41ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
42ca632f556697d45d67ed5cada7cedf3ddfe0db4bGrant Likely#include "spi-fsl-lib.h"
43e8beacbb85a5c1de1117400c5ddb450514a8372cAndreas Larsson#include "spi-fsl-cpm.h"
44e8beacbb85a5c1de1117400c5ddb450514a8372cAndreas Larsson#include "spi-fsl-spi.h"
45ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
46c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson#define TYPE_FSL	0
47447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson#define TYPE_GRLIB	1
48c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson
49c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larssonstruct fsl_spi_match_data {
50c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson	int type;
51c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson};
52c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson
53c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larssonstatic struct fsl_spi_match_data of_fsl_spi_fsl_config = {
54c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson	.type = TYPE_FSL,
55c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson};
56c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson
57447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larssonstatic struct fsl_spi_match_data of_fsl_spi_grlib_config = {
58447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	.type = TYPE_GRLIB,
59447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson};
60447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson
613aea901d6bb43c2809077cf2b2e75d9e836941a1Jingoo Hanstatic const struct of_device_id of_fsl_spi_match[] = {
62c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson	{
63c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson		.compatible = "fsl,spi",
64c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson		.data = &of_fsl_spi_fsl_config,
65c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson	},
66447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	{
67447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		.compatible = "aeroflexgaisler,spictrl",
68447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		.data = &of_fsl_spi_grlib_config,
69447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	},
70c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson	{}
71c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson};
72c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas LarssonMODULE_DEVICE_TABLE(of, of_fsl_spi_match);
73c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson
74c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larssonstatic int fsl_spi_get_type(struct device *dev)
75c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson{
76c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson	const struct of_device_id *match;
77c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson
78c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson	if (dev->of_node) {
79c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson		match = of_match_node(of_fsl_spi_match, dev->of_node);
80c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson		if (match && match->data)
81c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson			return ((struct fsl_spi_match_data *)match->data)->type;
82c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson	}
83c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson	return TYPE_FSL;
84c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson}
85c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson
86b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic void fsl_spi_change_mode(struct spi_device *spi)
87a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov{
88a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
89a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov	struct spi_mpc8xxx_cs *cs = spi->controller_state;
90b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	struct fsl_spi_reg *reg_base = mspi->reg_base;
91b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	__be32 __iomem *mode = &reg_base->mode;
92a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov	unsigned long flags;
93a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov
94a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov	if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
95a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov		return;
96a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov
97a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov	/* Turn off IRQs locally to minimize time that SPI is disabled. */
98a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov	local_irq_save(flags);
99a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov
100a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov	/* Turn off SPI unit prior changing mode */
101a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov	mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
102a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov
1034c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	/* When in CPM mode, we need to reinit tx and rx. */
1044c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	if (mspi->flags & SPI_CPM_MODE) {
105e8beacbb85a5c1de1117400c5ddb450514a8372cAndreas Larsson		fsl_spi_cpm_reinit_txrx(mspi);
1064c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	}
107f9218c2a60facc6ff9a793a9d9ab956194d70012Joakim Tjernlund	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
108a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov	local_irq_restore(flags);
109a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov}
110a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov
111b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic void fsl_spi_chipselect(struct spi_device *spi, int value)
112ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala{
113575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
1145039a86973cd35bdb2f64d28ee12f13fe2bb5a4cKenth Eriksson	struct fsl_spi_platform_data *pdata;
115364fdbc00fbdd409ade63500710123fe323aa164Anton Vorontsov	bool pol = spi->mode & SPI_CS_HIGH;
116575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
117ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
1185039a86973cd35bdb2f64d28ee12f13fe2bb5a4cKenth Eriksson	pdata = spi->dev.parent->parent->platform_data;
1195039a86973cd35bdb2f64d28ee12f13fe2bb5a4cKenth Eriksson
120ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	if (value == BITBANG_CS_INACTIVE) {
121364fdbc00fbdd409ade63500710123fe323aa164Anton Vorontsov		if (pdata->cs_control)
122364fdbc00fbdd409ade63500710123fe323aa164Anton Vorontsov			pdata->cs_control(spi, !pol);
123ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	}
124ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
125ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	if (value == BITBANG_CS_ACTIVE) {
126575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov		mpc8xxx_spi->rx_shift = cs->rx_shift;
127575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov		mpc8xxx_spi->tx_shift = cs->tx_shift;
128575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov		mpc8xxx_spi->get_rx = cs->get_rx;
129575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov		mpc8xxx_spi->get_tx = cs->get_tx;
130c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
131b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		fsl_spi_change_mode(spi);
132a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov
133364fdbc00fbdd409ade63500710123fe323aa164Anton Vorontsov		if (pdata->cs_control)
134364fdbc00fbdd409ade63500710123fe323aa164Anton Vorontsov			pdata->cs_control(spi, pol);
135ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	}
136ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala}
137ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
138b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larssonstatic void fsl_spi_qe_cpu_set_shifts(u32 *rx_shift, u32 *tx_shift,
139b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson				      int bits_per_word, int msb_first)
140b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson{
141b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson	*rx_shift = 0;
142b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson	*tx_shift = 0;
143b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson	if (msb_first) {
144b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson		if (bits_per_word <= 8) {
145b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson			*rx_shift = 16;
146b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson			*tx_shift = 24;
147b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson		} else if (bits_per_word <= 16) {
148b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson			*rx_shift = 16;
149b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson			*tx_shift = 16;
150b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson		}
151b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson	} else {
152b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson		if (bits_per_word <= 8)
153b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson			*rx_shift = 8;
154b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson	}
155b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson}
156b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson
157447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larssonstatic void fsl_spi_grlib_set_shifts(u32 *rx_shift, u32 *tx_shift,
158447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson				     int bits_per_word, int msb_first)
159447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson{
160447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	*rx_shift = 0;
161447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	*tx_shift = 0;
162447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	if (bits_per_word <= 16) {
163447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		if (msb_first) {
164447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson			*rx_shift = 16; /* LSB in bit 16 */
165447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson			*tx_shift = 32 - bits_per_word; /* MSB in bit 31 */
166447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		} else {
167447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson			*rx_shift = 16 - bits_per_word; /* MSB in bit 15 */
168447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		}
169447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	}
170447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson}
171447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson
172b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
173b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu				struct spi_device *spi,
174b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu				struct mpc8xxx_spi *mpc8xxx_spi,
175b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu				int bits_per_word)
176ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala{
177c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	cs->rx_shift = 0;
178c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	cs->tx_shift = 0;
179ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	if (bits_per_word <= 8) {
180575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov		cs->get_rx = mpc8xxx_spi_rx_buf_u8;
181575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov		cs->get_tx = mpc8xxx_spi_tx_buf_u8;
182ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	} else if (bits_per_word <= 16) {
183575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov		cs->get_rx = mpc8xxx_spi_rx_buf_u16;
184575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov		cs->get_tx = mpc8xxx_spi_tx_buf_u16;
185ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	} else if (bits_per_word <= 32) {
186575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov		cs->get_rx = mpc8xxx_spi_rx_buf_u32;
187575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov		cs->get_tx = mpc8xxx_spi_tx_buf_u32;
188ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	} else
189ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala		return -EINVAL;
190ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
191b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson	if (mpc8xxx_spi->set_shifts)
192b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson		mpc8xxx_spi->set_shifts(&cs->rx_shift, &cs->tx_shift,
193b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson					bits_per_word,
194b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson					!(spi->mode & SPI_LSB_FIRST));
195b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson
196575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	mpc8xxx_spi->rx_shift = cs->rx_shift;
197575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	mpc8xxx_spi->tx_shift = cs->tx_shift;
198575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	mpc8xxx_spi->get_rx = cs->get_rx;
199575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	mpc8xxx_spi->get_tx = cs->get_tx;
200ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
2010398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	return bits_per_word;
2020398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund}
2030398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund
204b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic int mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
205b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu				struct spi_device *spi,
206b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu				int bits_per_word)
2070398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund{
2080398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	/* QE uses Little Endian for words > 8
2090398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	 * so transform all words > 8 into 8 bits
2100398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	 * Unfortnatly that doesn't work for LSB so
2110398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	 * reject these for now */
2120398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	/* Note: 32 bits word, LSB works iff
2130398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	 * tfcr/rfcr is set to CPMFCR_GBL */
2140398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	if (spi->mode & SPI_LSB_FIRST &&
2150398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	    bits_per_word > 8)
2160398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund		return -EINVAL;
2170398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	if (bits_per_word > 8)
2180398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund		return 8; /* pretend its 8 bits */
2190398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	return bits_per_word;
2200398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund}
2210398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund
222b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic int fsl_spi_setup_transfer(struct spi_device *spi,
223b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu					struct spi_transfer *t)
2240398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund{
2250398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	struct mpc8xxx_spi *mpc8xxx_spi;
226b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	int bits_per_word = 0;
2270398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	u8 pm;
228b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	u32 hz = 0;
2290398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
2300398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund
2310398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	mpc8xxx_spi = spi_master_get_devdata(spi->master);
2320398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund
2330398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	if (t) {
2340398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund		bits_per_word = t->bits_per_word;
2350398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund		hz = t->speed_hz;
2360398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	}
2370398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund
2380398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	/* spi_transfer level calls that work per-word */
2390398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	if (!bits_per_word)
2400398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund		bits_per_word = spi->bits_per_word;
2410398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund
2420398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	if (!hz)
2430398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund		hz = spi->max_speed_hz;
2440398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund
2450398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
2460398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund		bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
2470398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund							   mpc8xxx_spi,
2480398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund							   bits_per_word);
2490398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	else if (mpc8xxx_spi->flags & SPI_QE)
2500398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund		bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
2510398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund							  bits_per_word);
2520398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund
2530398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund	if (bits_per_word < 0)
2540398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund		return bits_per_word;
2550398fb70940e1f10939d6126eafb760bd48d1566Joakim Tjernlund
256ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	if (bits_per_word == 32)
257ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala		bits_per_word = 0;
258ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	else
259ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala		bits_per_word = bits_per_word - 1;
260ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
26132421daaf8236b0fd6e032f6b1dd8086ccae2a46Anton Vorontsov	/* mask out bits we are going to set */
262c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	cs->hw_mode &= ~(SPMODE_LEN(0xF) | SPMODE_DIV16
263c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund				  | SPMODE_PM(0xF));
264c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
265c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	cs->hw_mode |= SPMODE_LEN(bits_per_word);
266c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
267575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	if ((mpc8xxx_spi->spibrg / hz) > 64) {
26853604dbe1371c3c4458c2d741adbd8cfd8fe8e79Peter Korsgaard		cs->hw_mode |= SPMODE_DIV16;
2694f4517c45f325ba511458465430a52864a5d0d30Ernst Schwab		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
270fd8a11e100b463811f41266ea3880c830f3359eaAnton Vorontsov
271fd8a11e100b463811f41266ea3880c830f3359eaAnton Vorontsov		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
272fd8a11e100b463811f41266ea3880c830f3359eaAnton Vorontsov			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
273575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov			  hz, mpc8xxx_spi->spibrg / 1024);
274fd8a11e100b463811f41266ea3880c830f3359eaAnton Vorontsov		if (pm > 16)
27553604dbe1371c3c4458c2d741adbd8cfd8fe8e79Peter Korsgaard			pm = 16;
276b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	} else {
2774f4517c45f325ba511458465430a52864a5d0d30Ernst Schwab		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
278b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	}
279a61f5345eba34772a71523227de890a28410f320Chen Gong	if (pm)
280a61f5345eba34772a71523227de890a28410f320Chen Gong		pm--;
281a61f5345eba34772a71523227de890a28410f320Chen Gong
282a61f5345eba34772a71523227de890a28410f320Chen Gong	cs->hw_mode |= SPMODE_PM(pm);
283a35c1710956f7aef06f58d22d343d7b948fbc272Anton Vorontsov
284b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	fsl_spi_change_mode(spi);
285c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	return 0;
286c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund}
287ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
288b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
2894c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov				struct spi_transfer *t, unsigned int len)
2904c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov{
2914c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	u32 word;
292b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	struct fsl_spi_reg *reg_base = mspi->reg_base;
2934c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
2944c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	mspi->count = len;
2954c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
2964c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	/* enable rx ints */
297b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
2984c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
2994c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	/* transmit word */
3004c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	word = mspi->get_tx(mspi);
301b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
3024c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
3034c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	return 0;
3044c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov}
3054c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
306b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
3074c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov			    bool is_dma_mapped)
3084c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov{
3094c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
310b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	struct fsl_spi_reg *reg_base;
3114c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	unsigned int len = t->len;
3124c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	u8 bits_per_word;
3134c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	int ret;
314c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
315b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	reg_base = mpc8xxx_spi->reg_base;
316c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	bits_per_word = spi->bits_per_word;
317c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	if (t->bits_per_word)
318c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund		bits_per_word = t->bits_per_word;
3194c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
320aa77d96ba94326db4f50d2aa36602824dd03286aPeter Korsgaard	if (bits_per_word > 8) {
321aa77d96ba94326db4f50d2aa36602824dd03286aPeter Korsgaard		/* invalid length? */
322aa77d96ba94326db4f50d2aa36602824dd03286aPeter Korsgaard		if (len & 1)
323aa77d96ba94326db4f50d2aa36602824dd03286aPeter Korsgaard			return -EINVAL;
324c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund		len /= 2;
325aa77d96ba94326db4f50d2aa36602824dd03286aPeter Korsgaard	}
326aa77d96ba94326db4f50d2aa36602824dd03286aPeter Korsgaard	if (bits_per_word > 16) {
327aa77d96ba94326db4f50d2aa36602824dd03286aPeter Korsgaard		/* invalid length? */
328aa77d96ba94326db4f50d2aa36602824dd03286aPeter Korsgaard		if (len & 1)
329aa77d96ba94326db4f50d2aa36602824dd03286aPeter Korsgaard			return -EINVAL;
330c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund		len /= 2;
331aa77d96ba94326db4f50d2aa36602824dd03286aPeter Korsgaard	}
332aa77d96ba94326db4f50d2aa36602824dd03286aPeter Korsgaard
3334c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	mpc8xxx_spi->tx = t->tx_buf;
3344c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	mpc8xxx_spi->rx = t->rx_buf;
335c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
33616735d022f72b20ddbb2274b8e109f69575e9b2bWolfram Sang	reinit_completion(&mpc8xxx_spi->done);
337c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
3384c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
339b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		ret = fsl_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
3404c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	else
341b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		ret = fsl_spi_cpu_bufs(mpc8xxx_spi, t, len);
3424c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	if (ret)
3434c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov		return ret;
344c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
345575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	wait_for_completion(&mpc8xxx_spi->done);
346c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
347c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	/* disable rx ints */
348b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
349c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
3504c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
351b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		fsl_spi_cpm_bufs_complete(mpc8xxx_spi);
3524c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
353575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	return mpc8xxx_spi->count;
354c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund}
355c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
356b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic void fsl_spi_do_one_msg(struct spi_message *m)
357c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund{
358b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov	struct spi_device *spi = m->spi;
3594302a59629f7a0bd70fd1605d2b558597517372aStefan Roese	struct spi_transfer *t, *first;
360b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov	unsigned int cs_change;
361b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov	const int nsecs = 50;
362b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov	int status;
363b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov
3644302a59629f7a0bd70fd1605d2b558597517372aStefan Roese	/* Don't allow changes if CS is active */
3654302a59629f7a0bd70fd1605d2b558597517372aStefan Roese	first = list_first_entry(&m->transfers, struct spi_transfer,
3664302a59629f7a0bd70fd1605d2b558597517372aStefan Roese			transfer_list);
367b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov	list_for_each_entry(t, &m->transfers, transfer_list) {
3684302a59629f7a0bd70fd1605d2b558597517372aStefan Roese		if ((first->bits_per_word != t->bits_per_word) ||
3694302a59629f7a0bd70fd1605d2b558597517372aStefan Roese			(first->speed_hz != t->speed_hz)) {
370b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov			status = -EINVAL;
3714302a59629f7a0bd70fd1605d2b558597517372aStefan Roese			dev_err(&spi->dev,
3724302a59629f7a0bd70fd1605d2b558597517372aStefan Roese				"bits_per_word/speed_hz should be same for the same SPI transfer\n");
3734302a59629f7a0bd70fd1605d2b558597517372aStefan Roese			return;
3744302a59629f7a0bd70fd1605d2b558597517372aStefan Roese		}
3754302a59629f7a0bd70fd1605d2b558597517372aStefan Roese	}
376b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov
3774302a59629f7a0bd70fd1605d2b558597517372aStefan Roese	cs_change = 1;
3784302a59629f7a0bd70fd1605d2b558597517372aStefan Roese	status = -EINVAL;
3794302a59629f7a0bd70fd1605d2b558597517372aStefan Roese	list_for_each_entry(t, &m->transfers, transfer_list) {
3804302a59629f7a0bd70fd1605d2b558597517372aStefan Roese		if (t->bits_per_word || t->speed_hz) {
381b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov			if (cs_change)
382b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu				status = fsl_spi_setup_transfer(spi, t);
383b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov			if (status < 0)
384c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund				break;
385b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov		}
386c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
387b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov		if (cs_change) {
388b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu			fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
389b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov			ndelay(nsecs);
390b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov		}
391b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov		cs_change = t->cs_change;
392b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov		if (t->len)
393b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu			status = fsl_spi_bufs(spi, t, m->is_dma_mapped);
394b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov		if (status) {
395b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov			status = -EMSGSIZE;
396b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov			break;
397c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund		}
398b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov		m->actual_length += t->len;
399c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
400b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov		if (t->delay_usecs)
401b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov			udelay(t->delay_usecs);
402c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
403b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov		if (cs_change) {
404c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund			ndelay(nsecs);
405b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu			fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
406b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov			ndelay(nsecs);
407c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund		}
408b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov	}
409b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov
410b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov	m->status = status;
4110a6d38795a405c49ea0012f04173613382def58cAxel Lin	if (m->complete)
4120a6d38795a405c49ea0012f04173613382def58cAxel Lin		m->complete(m->context);
413b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov
414b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov	if (status || !cs_change) {
415b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov		ndelay(nsecs);
416b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
417b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov	}
418b9b9af11fe35f509899fc5ff242b68d3299c3aefAnton Vorontsov
419b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	fsl_spi_setup_transfer(spi, NULL);
420ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala}
421ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
422b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic int fsl_spi_setup(struct spi_device *spi)
423ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala{
424575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	struct mpc8xxx_spi *mpc8xxx_spi;
425b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	struct fsl_spi_reg *reg_base;
426ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	int retval;
427c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	u32 hw_mode;
428d9f26748128c73ec6bed2846ca52fb1c2edc3cedAxel Lin	struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi);
429ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
430ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	if (!spi->max_speed_hz)
431ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala		return -EINVAL;
432ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
433c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	if (!cs) {
434d9f26748128c73ec6bed2846ca52fb1c2edc3cedAxel Lin		cs = kzalloc(sizeof(*cs), GFP_KERNEL);
435c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund		if (!cs)
436c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund			return -ENOMEM;
437d9f26748128c73ec6bed2846ca52fb1c2edc3cedAxel Lin		spi_set_ctldata(spi, cs);
438c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	}
439575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	mpc8xxx_spi = spi_master_get_devdata(spi->master);
440ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
441b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	reg_base = mpc8xxx_spi->reg_base;
442b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu
44388393161210493e317ae391696ee8ef463cb3c23Thomas Weber	hw_mode = cs->hw_mode; /* Save original settings */
444b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	cs->hw_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
445c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	/* mask out bits we are going to set */
446c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
447c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund			 | SPMODE_REV | SPMODE_LOOP);
448c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
449c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	if (spi->mode & SPI_CPHA)
450c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund		cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK;
451c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	if (spi->mode & SPI_CPOL)
452c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund		cs->hw_mode |= SPMODE_CI_INACTIVEHIGH;
453c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	if (!(spi->mode & SPI_LSB_FIRST))
454c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund		cs->hw_mode |= SPMODE_REV;
455c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	if (spi->mode & SPI_LOOP)
456c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund		cs->hw_mode |= SPMODE_LOOP;
457c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
458b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	retval = fsl_spi_setup_transfer(spi, NULL);
459c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	if (retval < 0) {
460c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund		cs->hw_mode = hw_mode; /* Restore settings */
461ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala		return retval;
462c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	}
463f482cd0ff506cd74c75edceec4b737c46c60cb12Andreas Larsson
46476a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson	if (mpc8xxx_spi->type == TYPE_GRLIB) {
46576a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		if (gpio_is_valid(spi->cs_gpio)) {
46676a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson			int desel;
46776a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson
46876a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson			retval = gpio_request(spi->cs_gpio,
46976a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson					      dev_name(&spi->dev));
47076a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson			if (retval)
47176a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson				return retval;
47276a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson
47376a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson			desel = !(spi->mode & SPI_CS_HIGH);
47476a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson			retval = gpio_direction_output(spi->cs_gpio, desel);
47576a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson			if (retval) {
47676a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson				gpio_free(spi->cs_gpio);
47776a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson				return retval;
47876a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson			}
47976a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		} else if (spi->cs_gpio != -ENOENT) {
48076a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson			if (spi->cs_gpio < 0)
48176a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson				return spi->cs_gpio;
48276a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson			return -EINVAL;
48376a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		}
48476a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		/* When spi->cs_gpio == -ENOENT, a hole in the phandle list
48576a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		 * indicates to use native chipselect if present, or allow for
48676a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		 * an always selected chip
48776a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		 */
48876a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson	}
48976a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson
490f482cd0ff506cd74c75edceec4b737c46c60cb12Andreas Larsson	/* Initialize chipselect - might be active for SPI_CS_HIGH mode */
491f482cd0ff506cd74c75edceec4b737c46c60cb12Andreas Larsson	fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
492f482cd0ff506cd74c75edceec4b737c46c60cb12Andreas Larsson
493ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	return 0;
494ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala}
495ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
49676a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larssonstatic void fsl_spi_cleanup(struct spi_device *spi)
49776a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson{
49876a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
499d9f26748128c73ec6bed2846ca52fb1c2edc3cedAxel Lin	struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi);
50076a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson
50176a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson	if (mpc8xxx_spi->type == TYPE_GRLIB && gpio_is_valid(spi->cs_gpio))
50276a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		gpio_free(spi->cs_gpio);
503d9f26748128c73ec6bed2846ca52fb1c2edc3cedAxel Lin
504d9f26748128c73ec6bed2846ca52fb1c2edc3cedAxel Lin	kfree(cs);
505d9f26748128c73ec6bed2846ca52fb1c2edc3cedAxel Lin	spi_set_ctldata(spi, NULL);
50676a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson}
50776a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson
508b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
5094c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov{
510b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	struct fsl_spi_reg *reg_base = mspi->reg_base;
511b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu
5124c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	/* We need handle RX first */
5134c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	if (events & SPIE_NE) {
514b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		u32 rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
5154c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
5164c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov		if (mspi->rx)
5174c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov			mspi->get_rx(rx_data, mspi);
518ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	}
519ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
5204c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	if ((events & SPIE_NF) == 0)
521ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala		/* spin until TX is done */
5224c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov		while (((events =
523b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu			mpc8xxx_spi_read_reg(&reg_base->event)) &
524ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala						SPIE_NF) == 0)
5259effb959dee0919991362541048479d94bd1f6e0Anton Vorontsov			cpu_relax();
526ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
5274c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	/* Clear the events */
528b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	mpc8xxx_spi_write_reg(&reg_base->event, events);
5294c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
5304c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	mspi->count -= 1;
5314c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	if (mspi->count) {
5324c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov		u32 word = mspi->get_tx(mspi);
5334c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
534b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
535ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	} else {
5364c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov		complete(&mspi->done);
537ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	}
5384c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov}
539ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
540b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
5414c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov{
5424c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	struct mpc8xxx_spi *mspi = context_data;
5434c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	irqreturn_t ret = IRQ_NONE;
5444c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	u32 events;
545b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	struct fsl_spi_reg *reg_base = mspi->reg_base;
5464c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
5474c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	/* Get interrupt events(tx/rx) */
548b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	events = mpc8xxx_spi_read_reg(&reg_base->event);
5494c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	if (events)
5504c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov		ret = IRQ_HANDLED;
5514c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
5524c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
5534c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
5544c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	if (mspi->flags & SPI_CPM_MODE)
555b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		fsl_spi_cpm_irq(mspi, events);
5564c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	else
557b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		fsl_spi_cpu_irq(mspi, events);
558ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
559ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	return ret;
560ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala}
5614c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
562b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic void fsl_spi_remove(struct mpc8xxx_spi *mspi)
56387ec0e98cfdd8b68da6a7f9e70142ffc0e404fbbAnton Vorontsov{
564b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	iounmap(mspi->reg_base);
565b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	fsl_spi_cpm_free(mspi);
56687ec0e98cfdd8b68da6a7f9e70142ffc0e404fbbAnton Vorontsov}
56787ec0e98cfdd8b68da6a7f9e70142ffc0e404fbbAnton Vorontsov
568447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larssonstatic void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
569447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson{
570447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
571447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base;
572447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	u32 slvsel;
573447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	u16 cs = spi->chip_select;
574447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson
57576a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson	if (gpio_is_valid(spi->cs_gpio)) {
57676a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		gpio_set_value(spi->cs_gpio, on);
57776a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson	} else if (cs < mpc8xxx_spi->native_chipselects) {
57876a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		slvsel = mpc8xxx_spi_read_reg(&reg_base->slvsel);
57976a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs));
58076a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		mpc8xxx_spi_write_reg(&reg_base->slvsel, slvsel);
58176a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson	}
582447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson}
583447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson
584447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larssonstatic void fsl_spi_grlib_probe(struct device *dev)
585447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson{
5868074cf063e410a2c0cf1704c3b31002e21f5df7cJingoo Han	struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
587447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	struct spi_master *master = dev_get_drvdata(dev);
588447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
589447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base;
590447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	int mbits;
591447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	u32 capabilities;
592447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson
593447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	capabilities = mpc8xxx_spi_read_reg(&reg_base->cap);
594447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson
595447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	mpc8xxx_spi->set_shifts = fsl_spi_grlib_set_shifts;
596447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	mbits = SPCAP_MAXWLEN(capabilities);
597447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	if (mbits)
598447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		mpc8xxx_spi->max_bits_per_word = mbits + 1;
599447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson
60076a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson	mpc8xxx_spi->native_chipselects = 0;
601447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	if (SPCAP_SSEN(capabilities)) {
60276a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson		mpc8xxx_spi->native_chipselects = SPCAP_SSSZ(capabilities);
603447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		mpc8xxx_spi_write_reg(&reg_base->slvsel, 0xffffffff);
604447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	}
60576a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson	master->num_chipselect = mpc8xxx_spi->native_chipselects;
606447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	pdata->cs_control = fsl_spi_grlib_cs_control;
607447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson}
608447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson
609fd4a319bc933ae93e68935b21924a9ca4ba2d060Grant Likelystatic struct spi_master * fsl_spi_probe(struct device *dev,
610b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		struct resource *mem, unsigned int irq)
611ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala{
6128074cf063e410a2c0cf1704c3b31002e21f5df7cJingoo Han	struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
613ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	struct spi_master *master;
614575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	struct mpc8xxx_spi *mpc8xxx_spi;
615b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	struct fsl_spi_reg *reg_base;
616ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	u32 regval;
617ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	int ret = 0;
618ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
619575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
620ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	if (master == NULL) {
621ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala		ret = -ENOMEM;
622ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala		goto err;
623ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	}
624ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
62535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	dev_set_drvdata(dev, master);
626ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
627b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	ret = mpc8xxx_spi_probe(dev, mem, irq);
628b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	if (ret)
629b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		goto err_probe;
630e7db06b5d5afcef15c4c3e61c3a7441ed7ad1407David Brownell
631b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	master->setup = fsl_spi_setup;
63276a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson	master->cleanup = fsl_spi_cleanup;
633575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov
634575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	mpc8xxx_spi = spi_master_get_devdata(master);
635b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg;
636b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	mpc8xxx_spi->spi_remove = fsl_spi_remove;
6378922a366ddd20964e3542e12f0315a8a88b3a638Andreas Larsson	mpc8xxx_spi->max_bits_per_word = 32;
638c3f3e7717f1cf01d9117a98ed89decc41d7cb5dbAndreas Larsson	mpc8xxx_spi->type = fsl_spi_get_type(dev);
639575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov
640b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	ret = fsl_spi_cpm_init(mpc8xxx_spi);
6414c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov	if (ret)
6424c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov		goto err_cpm_init;
6434c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov
644447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
645447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	if (mpc8xxx_spi->reg_base == NULL) {
646447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		ret = -ENOMEM;
647447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		goto err_ioremap;
648447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	}
649447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson
650447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	if (mpc8xxx_spi->type == TYPE_GRLIB)
651447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		fsl_spi_grlib_probe(dev);
652447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson
653f734394d861fe71eafa28d6c28199d9847c5a319Axel Lin	master->bits_per_word_mask =
654f734394d861fe71eafa28d6c28199d9847c5a319Axel Lin		(SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32)) &
655f734394d861fe71eafa28d6c28199d9847c5a319Axel Lin		SPI_BPW_RANGE_MASK(1, mpc8xxx_spi->max_bits_per_word);
656f734394d861fe71eafa28d6c28199d9847c5a319Axel Lin
657b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
658b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson		mpc8xxx_spi->set_shifts = fsl_spi_qe_cpu_set_shifts;
659b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson
660b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson	if (mpc8xxx_spi->set_shifts)
661b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson		/* 8 bits per word and MSB first */
662b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson		mpc8xxx_spi->set_shifts(&mpc8xxx_spi->rx_shift,
663b48c4e3c944e8c52dcb0f477e9d80da045c7cab4Andreas Larsson					&mpc8xxx_spi->tx_shift, 8, 1);
664f29ba280ecb46331c1f6842b094808af01131422Joakim Tjernlund
665ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	/* Register for SPI Interrupt */
666b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq,
667b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu			  0, "fsl_spi", mpc8xxx_spi);
668ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
669ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	if (ret != 0)
670b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		goto free_irq;
671ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
672b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	reg_base = mpc8xxx_spi->reg_base;
673ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
674ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	/* SPI controller initializations */
675b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	mpc8xxx_spi_write_reg(&reg_base->mode, 0);
676b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
677b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	mpc8xxx_spi_write_reg(&reg_base->command, 0);
678b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
679ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
680ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	/* Enable SPI interface */
681ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
6828922a366ddd20964e3542e12f0315a8a88b3a638Andreas Larsson	if (mpc8xxx_spi->max_bits_per_word < 8) {
6838922a366ddd20964e3542e12f0315a8a88b3a638Andreas Larsson		regval &= ~SPMODE_LEN(0xF);
6848922a366ddd20964e3542e12f0315a8a88b3a638Andreas Larsson		regval |= SPMODE_LEN(mpc8xxx_spi->max_bits_per_word - 1);
6858922a366ddd20964e3542e12f0315a8a88b3a638Andreas Larsson	}
68687ec0e98cfdd8b68da6a7f9e70142ffc0e404fbbAnton Vorontsov	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
687f29ba280ecb46331c1f6842b094808af01131422Joakim Tjernlund		regval |= SPMODE_OP;
688f29ba280ecb46331c1f6842b094808af01131422Joakim Tjernlund
689b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	mpc8xxx_spi_write_reg(&reg_base->mode, regval);
690c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund
691c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	ret = spi_register_master(master);
692c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund	if (ret < 0)
693c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlund		goto unreg_master;
694ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
695b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
69687ec0e98cfdd8b68da6a7f9e70142ffc0e404fbbAnton Vorontsov		 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
697ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
69835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	return master;
699ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
700c9bfcb3151040cff6714542d1da04ccd7e2d3efcJoakim Tjernlundunreg_master:
701575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
702b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hufree_irq:
703b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	iounmap(mpc8xxx_spi->reg_base);
7044c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsoverr_ioremap:
705b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	fsl_spi_cpm_free(mpc8xxx_spi);
7064c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsoverr_cpm_init:
707b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Huerr_probe:
708ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	spi_master_put(master);
709ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Galaerr:
71035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	return ERR_PTR(ret);
711ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala}
712ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
713b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic void fsl_spi_cs_control(struct spi_device *spi, bool on)
71435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov{
715067aa4815a9bc12a569d8a06afef50ba5773afbfHerton Ronaldo Krzesinski	struct device *dev = spi->dev.parent->parent;
7168074cf063e410a2c0cf1704c3b31002e21f5df7cJingoo Han	struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
7178074cf063e410a2c0cf1704c3b31002e21f5df7cJingoo Han	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
71835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	u16 cs = spi->chip_select;
71935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	int gpio = pinfo->gpios[cs];
72035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	bool alow = pinfo->alow_flags[cs];
72135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
72235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	gpio_set_value(gpio, on ^ alow);
72335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov}
72435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
725b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic int of_fsl_spi_get_chipselects(struct device *dev)
72635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov{
72761c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	struct device_node *np = dev->of_node;
7288074cf063e410a2c0cf1704c3b31002e21f5df7cJingoo Han	struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
729575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
730e80beb27d2f81a1c3c8887e0e0a82d77bb392d28Grant Likely	int ngpios;
73135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	int i = 0;
73235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	int ret;
73335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
73435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	ngpios = of_gpio_count(np);
735e80beb27d2f81a1c3c8887e0e0a82d77bb392d28Grant Likely	if (ngpios <= 0) {
73635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		/*
73735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		 * SPI w/o chip-select line. One SPI device is still permitted
73835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		 * though.
73935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		 */
74035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		pdata->max_chipselect = 1;
74135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		return 0;
74235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	}
74335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
744021415468c889979117b1a07b96f7e36de33e995Roel Kluin	pinfo->gpios = kmalloc(ngpios * sizeof(*pinfo->gpios), GFP_KERNEL);
74535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	if (!pinfo->gpios)
74635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		return -ENOMEM;
747021415468c889979117b1a07b96f7e36de33e995Roel Kluin	memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios));
74835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
749021415468c889979117b1a07b96f7e36de33e995Roel Kluin	pinfo->alow_flags = kzalloc(ngpios * sizeof(*pinfo->alow_flags),
75035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov				    GFP_KERNEL);
75135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	if (!pinfo->alow_flags) {
75235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		ret = -ENOMEM;
75335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		goto err_alloc_flags;
75435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	}
75535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
75635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	for (; i < ngpios; i++) {
75735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		int gpio;
75835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		enum of_gpio_flags flags;
75935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
76035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		gpio = of_get_gpio_flags(np, i, &flags);
76135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		if (!gpio_is_valid(gpio)) {
76235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov			dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
763783058fd582a1d8afbbf1d4e9b7918614a4550ffAnton Vorontsov			ret = gpio;
76435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov			goto err_loop;
76535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		}
76635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
76735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		ret = gpio_request(gpio, dev_name(dev));
76835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		if (ret) {
76935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov			dev_err(dev, "can't request gpio #%d: %d\n", i, ret);
77035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov			goto err_loop;
77135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		}
77235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
77335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		pinfo->gpios[i] = gpio;
77435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW;
77535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
77635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		ret = gpio_direction_output(pinfo->gpios[i],
77735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov					    pinfo->alow_flags[i]);
77835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		if (ret) {
77935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov			dev_err(dev, "can't set output direction for gpio "
78035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov				"#%d: %d\n", i, ret);
78135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov			goto err_loop;
78235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		}
78335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	}
78435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
78535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	pdata->max_chipselect = ngpios;
786b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	pdata->cs_control = fsl_spi_cs_control;
78735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
78835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	return 0;
78935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
79035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsoverr_loop:
79135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	while (i >= 0) {
79235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		if (gpio_is_valid(pinfo->gpios[i]))
79335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov			gpio_free(pinfo->gpios[i]);
79435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		i--;
79535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	}
79635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
79735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	kfree(pinfo->alow_flags);
79835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	pinfo->alow_flags = NULL;
79935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsoverr_alloc_flags:
80035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	kfree(pinfo->gpios);
80135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	pinfo->gpios = NULL;
80235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	return ret;
80335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov}
80435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
805b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic int of_fsl_spi_free_chipselects(struct device *dev)
80635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov{
8078074cf063e410a2c0cf1704c3b31002e21f5df7cJingoo Han	struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
808575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
80935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	int i;
81035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
81135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	if (!pinfo->gpios)
81235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		return 0;
81335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
81435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	for (i = 0; i < pdata->max_chipselect; i++) {
81535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		if (gpio_is_valid(pinfo->gpios[i]))
81635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov			gpio_free(pinfo->gpios[i]);
81735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	}
81835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
81935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	kfree(pinfo->gpios);
82035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	kfree(pinfo->alow_flags);
82135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	return 0;
82235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov}
82335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
824fd4a319bc933ae93e68935b21924a9ca4ba2d060Grant Likelystatic int of_fsl_spi_probe(struct platform_device *ofdev)
82535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov{
82635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	struct device *dev = &ofdev->dev;
82761c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	struct device_node *np = ofdev->dev.of_node;
82835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	struct spi_master *master;
82935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	struct resource mem;
830447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	int irq, type;
83135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	int ret = -ENOMEM;
83235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
83318d306d1375696b0e6b5b39e4744d7fa2ad5e170Grant Likely	ret = of_mpc8xxx_spi_probe(ofdev);
834b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	if (ret)
835b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		return ret;
83635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
837447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	type = fsl_spi_get_type(&ofdev->dev);
838447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	if (type == TYPE_FSL) {
839447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		ret = of_fsl_spi_get_chipselects(dev);
840447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		if (ret)
841447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson			goto err;
842447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	}
84335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
84435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	ret = of_address_to_resource(np, 0, &mem);
84535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	if (ret)
84635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		goto err;
84735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
848e8beacbb85a5c1de1117400c5ddb450514a8372cAndreas Larsson	irq = irq_of_parse_and_map(np, 0);
849e8beacbb85a5c1de1117400c5ddb450514a8372cAndreas Larsson	if (!irq) {
85035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		ret = -EINVAL;
85135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		goto err;
85235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	}
85335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
854e8beacbb85a5c1de1117400c5ddb450514a8372cAndreas Larsson	master = fsl_spi_probe(dev, &mem, irq);
85535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	if (IS_ERR(master)) {
85635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		ret = PTR_ERR(master);
85735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		goto err;
85835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	}
85935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
86035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	return 0;
86135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
86235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsoverr:
863447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	if (type == TYPE_FSL)
864447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		of_fsl_spi_free_chipselects(dev);
86535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	return ret;
86635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov}
86735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
868fd4a319bc933ae93e68935b21924a9ca4ba2d060Grant Likelystatic int of_fsl_spi_remove(struct platform_device *ofdev)
86935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov{
87024b5a82cf5709a4bc577f42fdaa61b23a7f58f08Jingoo Han	struct spi_master *master = platform_get_drvdata(ofdev);
871447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
87235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	int ret;
87335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
874575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	ret = mpc8xxx_spi_remove(&ofdev->dev);
87535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	if (ret)
87635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		return ret;
877447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson	if (mpc8xxx_spi->type == TYPE_FSL)
878447b0c7b939f1d9e4024edf07a471ce7b1bcf002Andreas Larsson		of_fsl_spi_free_chipselects(&ofdev->dev);
87935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	return 0;
88035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov}
88135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
88218d306d1375696b0e6b5b39e4744d7fa2ad5e170Grant Likelystatic struct platform_driver of_fsl_spi_driver = {
8834018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	.driver = {
884b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		.name = "fsl_spi",
8854018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.owner = THIS_MODULE,
886b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu		.of_match_table = of_fsl_spi_match,
8874018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	},
888b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	.probe		= of_fsl_spi_probe,
889fd4a319bc933ae93e68935b21924a9ca4ba2d060Grant Likely	.remove		= of_fsl_spi_remove,
89035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov};
89135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
89235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov#ifdef CONFIG_MPC832x_RDB
89335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov/*
894b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu * XXX XXX XXX
89535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
89635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov * only. The driver should go away soon, since newer MPC8323E-RDB's device
89735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov * tree can work with OpenFirmware driver. But for now we support old trees
89835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov * as well.
89935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov */
900fd4a319bc933ae93e68935b21924a9ca4ba2d060Grant Likelystatic int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
90135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov{
90235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	struct resource *mem;
903e9a172f074ba85de144e63b0786c7c5c5ba93c3aUwe Kleine-König	int irq;
90435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	struct spi_master *master;
90535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
9068074cf063e410a2c0cf1704c3b31002e21f5df7cJingoo Han	if (!dev_get_platdata(&pdev->dev))
90735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		return -EINVAL;
90835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
90935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
91035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	if (!mem)
91135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		return -EINVAL;
91235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
91335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	irq = platform_get_irq(pdev, 0);
914e9a172f074ba85de144e63b0786c7c5c5ba93c3aUwe Kleine-König	if (irq <= 0)
91535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		return -EINVAL;
91635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
917b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu	master = fsl_spi_probe(&pdev->dev, mem, irq);
9188c6ffba0eddc8c110dbf444f51354ce42069abfcRusty Russell	return PTR_ERR_OR_ZERO(master);
91935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov}
92035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
921fd4a319bc933ae93e68935b21924a9ca4ba2d060Grant Likelystatic int plat_mpc8xxx_spi_remove(struct platform_device *pdev)
92235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov{
923575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	return mpc8xxx_spi_remove(&pdev->dev);
92435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov}
92535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
926575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton VorontsovMODULE_ALIAS("platform:mpc8xxx_spi");
927575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsovstatic struct platform_driver mpc8xxx_spi_driver = {
928575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	.probe = plat_mpc8xxx_spi_probe,
929fd4a319bc933ae93e68935b21924a9ca4ba2d060Grant Likely	.remove = plat_mpc8xxx_spi_remove,
930ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	.driver = {
931575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov		.name = "mpc8xxx_spi",
9327e38c3c4453bdb5ffdf8bf0ff0d9a760540f0893Kay Sievers		.owner = THIS_MODULE,
933ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala	},
934ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala};
935ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
93635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsovstatic bool legacy_driver_failed;
93735b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
93835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsovstatic void __init legacy_driver_register(void)
93935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov{
940575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	legacy_driver_failed = platform_driver_register(&mpc8xxx_spi_driver);
94135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov}
94235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
94335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsovstatic void __exit legacy_driver_unregister(void)
94435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov{
94535b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	if (legacy_driver_failed)
94635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov		return;
947575c5807f6842422e9fe2432fd48dfcc1d7aef41Anton Vorontsov	platform_driver_unregister(&mpc8xxx_spi_driver);
94835b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov}
94935b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov#else
95035b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsovstatic void __init legacy_driver_register(void) {}
95135b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsovstatic void __exit legacy_driver_unregister(void) {}
95235b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov#endif /* CONFIG_MPC832x_RDB */
95335b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov
954b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic int __init fsl_spi_init(void)
955ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala{
95635b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	legacy_driver_register();
95718d306d1375696b0e6b5b39e4744d7fa2ad5e170Grant Likely	return platform_driver_register(&of_fsl_spi_driver);
958ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala}
959b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Humodule_init(fsl_spi_init);
960ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
961b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hustatic void __exit fsl_spi_exit(void)
962ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala{
96318d306d1375696b0e6b5b39e4744d7fa2ad5e170Grant Likely	platform_driver_unregister(&of_fsl_spi_driver);
96435b4b3c0c1265f1a7342574be393c157601401f0Anton Vorontsov	legacy_driver_unregister();
965ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala}
966b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Humodule_exit(fsl_spi_exit);
967ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala
968ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar GalaMODULE_AUTHOR("Kumar Gala");
969b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai HuMODULE_DESCRIPTION("Simple Freescale SPI Driver");
970ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar GalaMODULE_LICENSE("GPL");
971