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 = ®_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(®_base->mask, SPIM_NE); 2984c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov 2994c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov /* transmit word */ 3004c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov word = mspi->get_tx(mspi); 301b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu mpc8xxx_spi_write_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(®_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(®_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(®_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(®_base->event)) & 524ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala SPIE_NF) == 0) 5259effb959dee0919991362541048479d94bd1f6e0Anton Vorontsov cpu_relax(); 526ccf06998fe179ae2cc9517ed1d75433dc0b5032dKumar Gala 5274c1fba442960cfa2fd6333b9fec7d5b85c5fa29fAnton Vorontsov /* Clear the events */ 528b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu mpc8xxx_spi_write_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(®_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(®_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(®_base->slvsel); 57976a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs)); 58076a7498f691f4c315dba0747141eeee3ceb740dcAndreas Larsson mpc8xxx_spi_write_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(®_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(®_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(®_base->mode, 0); 676b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu mpc8xxx_spi_write_reg(®_base->mask, 0); 677b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu mpc8xxx_spi_write_reg(®_base->command, 0); 678b36ece832512c1a0afa54ff0a56d63492a1caf08Mingkai Hu mpc8xxx_spi_write_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(®_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