blob: be84e3a3640600136e5f1b72f6d6ee02b340f693 [file] [log] [blame]
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001/*
2 * SPI bus driver for the Topcliff PCH used by Intel SoCs
Grant Likely65308c42010-09-29 17:31:34 +09003 *
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06004 * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18 */
19
Grant Likely65308c42010-09-29 17:31:34 +090020#include <linux/delay.h>
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -060021#include <linux/pci.h>
22#include <linux/wait.h>
23#include <linux/spi/spi.h>
24#include <linux/interrupt.h>
25#include <linux/sched.h>
26#include <linux/spi/spidev.h>
27#include <linux/module.h>
28#include <linux/device.h>
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +090029#include <linux/platform_device.h>
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -060030
31/* Register offsets */
32#define PCH_SPCR 0x00 /* SPI control register */
33#define PCH_SPBRR 0x04 /* SPI baud rate register */
34#define PCH_SPSR 0x08 /* SPI status register */
35#define PCH_SPDWR 0x0C /* SPI write data register */
36#define PCH_SPDRR 0x10 /* SPI read data register */
37#define PCH_SSNXCR 0x18 /* SSN Expand Control Register */
38#define PCH_SRST 0x1C /* SPI reset register */
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +090039#define PCH_SPI_ADDRESS_SIZE 0x20
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -060040
41#define PCH_SPSR_TFD 0x000007C0
42#define PCH_SPSR_RFD 0x0000F800
43
44#define PCH_READABLE(x) (((x) & PCH_SPSR_RFD)>>11)
45#define PCH_WRITABLE(x) (((x) & PCH_SPSR_TFD)>>6)
46
47#define PCH_RX_THOLD 7
48#define PCH_RX_THOLD_MAX 15
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -060049
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -060050#define PCH_MAX_BAUDRATE 5000000
51#define PCH_MAX_FIFO_DEPTH 16
52
53#define STATUS_RUNNING 1
54#define STATUS_EXITING 2
55#define PCH_SLEEP_TIME 10
56
57#define PCH_ADDRESS_SIZE 0x20
58
59#define SSN_LOW 0x02U
60#define SSN_NO_CONTROL 0x00U
61#define PCH_MAX_CS 0xFF
62#define PCI_DEVICE_ID_GE_SPI 0x8816
63
64#define SPCR_SPE_BIT (1 << 0)
65#define SPCR_MSTR_BIT (1 << 1)
66#define SPCR_LSBF_BIT (1 << 4)
67#define SPCR_CPHA_BIT (1 << 5)
68#define SPCR_CPOL_BIT (1 << 6)
69#define SPCR_TFIE_BIT (1 << 8)
70#define SPCR_RFIE_BIT (1 << 9)
71#define SPCR_FIE_BIT (1 << 10)
72#define SPCR_ORIE_BIT (1 << 11)
73#define SPCR_MDFIE_BIT (1 << 12)
74#define SPCR_FICLR_BIT (1 << 24)
75#define SPSR_TFI_BIT (1 << 0)
76#define SPSR_RFI_BIT (1 << 1)
77#define SPSR_FI_BIT (1 << 2)
78#define SPBRR_SIZE_BIT (1 << 10)
79
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +090080#define PCH_ALL (SPCR_TFIE_BIT|SPCR_RFIE_BIT|SPCR_FIE_BIT|\
81 SPCR_ORIE_BIT|SPCR_MDFIE_BIT)
Grant Likely65308c42010-09-29 17:31:34 +090082
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -060083#define SPCR_RFIC_FIELD 20
84#define SPCR_TFIC_FIELD 16
85
86#define SPSR_INT_BITS 0x1F
87#define MASK_SPBRR_SPBR_BITS (~((1 << 10) - 1))
88#define MASK_RFIC_SPCR_BITS (~(0xf << 20))
89#define MASK_TFIC_SPCR_BITS (~(0xf000f << 12))
90
91#define PCH_CLOCK_HZ 50000000
92#define PCH_MAX_SPBR 1023
93
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +090094/* Definition for ML7213 by OKI SEMICONDUCTOR */
95#define PCI_VENDOR_ID_ROHM 0x10DB
96#define PCI_DEVICE_ID_ML7213_SPI 0x802c
97
98/*
99 * Set the number of SPI instance max
100 * Intel EG20T PCH : 1ch
101 * OKI SEMICONDUCTOR ML7213 IOH : 2ch
102*/
103#define PCH_SPI_MAX_DEV 2
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600104
105/**
106 * struct pch_spi_data - Holds the SPI channel specific details
107 * @io_remap_addr: The remapped PCI base address
108 * @master: Pointer to the SPI master structure
109 * @work: Reference to work queue handler
110 * @wk: Workqueue for carrying out execution of the
111 * requests
112 * @wait: Wait queue for waking up upon receiving an
113 * interrupt.
114 * @transfer_complete: Status of SPI Transfer
115 * @bcurrent_msg_processing: Status flag for message processing
116 * @lock: Lock for protecting this structure
117 * @queue: SPI Message queue
118 * @status: Status of the SPI driver
119 * @bpw_len: Length of data to be transferred in bits per
120 * word
121 * @transfer_active: Flag showing active transfer
122 * @tx_index: Transmit data count; for bookkeeping during
123 * transfer
124 * @rx_index: Receive data count; for bookkeeping during
125 * transfer
126 * @tx_buff: Buffer for data to be transmitted
127 * @rx_index: Buffer for Received data
128 * @n_curnt_chip: The chip number that this SPI driver currently
129 * operates on
130 * @current_chip: Reference to the current chip that this SPI
131 * driver currently operates on
132 * @current_msg: The current message that this SPI driver is
133 * handling
134 * @cur_trans: The current transfer that this SPI driver is
135 * handling
136 * @board_dat: Reference to the SPI device data structure
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900137 * @plat_dev: platform_device structure
138 * @ch: SPI channel number
139 * @irq_reg_sts: Status of IRQ registration
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600140 */
141struct pch_spi_data {
142 void __iomem *io_remap_addr;
143 struct spi_master *master;
144 struct work_struct work;
145 struct workqueue_struct *wk;
146 wait_queue_head_t wait;
147 u8 transfer_complete;
148 u8 bcurrent_msg_processing;
149 spinlock_t lock;
150 struct list_head queue;
151 u8 status;
152 u32 bpw_len;
153 u8 transfer_active;
154 u32 tx_index;
155 u32 rx_index;
156 u16 *pkt_tx_buff;
157 u16 *pkt_rx_buff;
158 u8 n_curnt_chip;
159 struct spi_device *current_chip;
160 struct spi_message *current_msg;
161 struct spi_transfer *cur_trans;
162 struct pch_spi_board_data *board_dat;
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900163 struct platform_device *plat_dev;
164 int ch;
165 u8 irq_reg_sts;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600166};
167
168/**
169 * struct pch_spi_board_data - Holds the SPI device specific details
170 * @pdev: Pointer to the PCI device
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600171 * @suspend_sts: Status of suspend
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900172 * @num: The number of SPI device instance
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600173 */
174struct pch_spi_board_data {
175 struct pci_dev *pdev;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600176 u8 suspend_sts;
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900177 int num;
178};
179
180struct pch_pd_dev_save {
181 int num;
182 struct platform_device *pd_save[PCH_SPI_MAX_DEV];
183 struct pch_spi_board_data *board_dat;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600184};
185
186static struct pci_device_id pch_spi_pcidev_id[] = {
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900187 { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI), 1, },
188 { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, },
189 { }
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600190};
191
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600192/**
193 * pch_spi_writereg() - Performs register writes
194 * @master: Pointer to struct spi_master.
195 * @idx: Register offset.
196 * @val: Value to be written to register.
197 */
198static inline void pch_spi_writereg(struct spi_master *master, int idx, u32 val)
199{
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600200 struct pch_spi_data *data = spi_master_get_devdata(master);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600201 iowrite32(val, (data->io_remap_addr + idx));
202}
203
204/**
205 * pch_spi_readreg() - Performs register reads
206 * @master: Pointer to struct spi_master.
207 * @idx: Register offset.
208 */
209static inline u32 pch_spi_readreg(struct spi_master *master, int idx)
210{
211 struct pch_spi_data *data = spi_master_get_devdata(master);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600212 return ioread32(data->io_remap_addr + idx);
213}
214
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600215static inline void pch_spi_setclr_reg(struct spi_master *master, int idx,
216 u32 set, u32 clr)
217{
218 u32 tmp = pch_spi_readreg(master, idx);
219 tmp = (tmp & ~clr) | set;
220 pch_spi_writereg(master, idx, tmp);
221}
222
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600223static void pch_spi_set_master_mode(struct spi_master *master)
224{
225 pch_spi_setclr_reg(master, PCH_SPCR, SPCR_MSTR_BIT, 0);
226}
227
228/**
229 * pch_spi_clear_fifo() - Clears the Transmit and Receive FIFOs
230 * @master: Pointer to struct spi_master.
231 */
232static void pch_spi_clear_fifo(struct spi_master *master)
233{
234 pch_spi_setclr_reg(master, PCH_SPCR, SPCR_FICLR_BIT, 0);
235 pch_spi_setclr_reg(master, PCH_SPCR, 0, SPCR_FICLR_BIT);
236}
237
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600238static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
239 void __iomem *io_remap_addr)
240{
241 u32 n_read, tx_index, rx_index, bpw_len;
242 u16 *pkt_rx_buffer, *pkt_tx_buff;
243 int read_cnt;
244 u32 reg_spcr_val;
245 void __iomem *spsr;
246 void __iomem *spdrr;
247 void __iomem *spdwr;
248
249 spsr = io_remap_addr + PCH_SPSR;
250 iowrite32(reg_spsr_val, spsr);
251
252 if (data->transfer_active) {
253 rx_index = data->rx_index;
254 tx_index = data->tx_index;
255 bpw_len = data->bpw_len;
256 pkt_rx_buffer = data->pkt_rx_buff;
257 pkt_tx_buff = data->pkt_tx_buff;
258
259 spdrr = io_remap_addr + PCH_SPDRR;
260 spdwr = io_remap_addr + PCH_SPDWR;
261
262 n_read = PCH_READABLE(reg_spsr_val);
263
264 for (read_cnt = 0; (read_cnt < n_read); read_cnt++) {
265 pkt_rx_buffer[rx_index++] = ioread32(spdrr);
266 if (tx_index < bpw_len)
267 iowrite32(pkt_tx_buff[tx_index++], spdwr);
268 }
269
270 /* disable RFI if not needed */
271 if ((bpw_len - rx_index) <= PCH_MAX_FIFO_DEPTH) {
272 reg_spcr_val = ioread32(io_remap_addr + PCH_SPCR);
Grant Likely65308c42010-09-29 17:31:34 +0900273 reg_spcr_val &= ~SPCR_RFIE_BIT; /* disable RFI */
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600274
275 /* reset rx threshold */
276 reg_spcr_val &= MASK_RFIC_SPCR_BITS;
277 reg_spcr_val |= (PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD);
278 iowrite32(((reg_spcr_val) &= (~(SPCR_RFIE_BIT))),
279 (io_remap_addr + PCH_SPCR));
280 }
281
282 /* update counts */
283 data->tx_index = tx_index;
284 data->rx_index = rx_index;
285
286 }
287
288 /* if transfer complete interrupt */
289 if (reg_spsr_val & SPSR_FI_BIT) {
290 /* disable FI & RFI interrupts */
Grant Likely65308c42010-09-29 17:31:34 +0900291 pch_spi_setclr_reg(data->master, PCH_SPCR, 0,
Tomoya MORINAGA9d32af62010-12-24 11:40:50 +0900292 SPCR_FIE_BIT | SPCR_RFIE_BIT);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600293
294 /* transfer is completed;inform pch_spi_process_messages */
295 data->transfer_complete = true;
296 wake_up(&data->wait);
297 }
298}
299
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600300/**
301 * pch_spi_handler() - Interrupt handler
302 * @irq: The interrupt number.
303 * @dev_id: Pointer to struct pch_spi_board_data.
304 */
305static irqreturn_t pch_spi_handler(int irq, void *dev_id)
306{
307 u32 reg_spsr_val;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600308 void __iomem *spsr;
309 void __iomem *io_remap_addr;
310 irqreturn_t ret = IRQ_NONE;
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900311 struct pch_spi_data *data = dev_id;
312 struct pch_spi_board_data *board_dat = data->board_dat;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600313
314 if (board_dat->suspend_sts) {
315 dev_dbg(&board_dat->pdev->dev,
316 "%s returning due to suspend\n", __func__);
317 return IRQ_NONE;
318 }
319
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600320 io_remap_addr = data->io_remap_addr;
321 spsr = io_remap_addr + PCH_SPSR;
322
323 reg_spsr_val = ioread32(spsr);
324
325 /* Check if the interrupt is for SPI device */
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600326 if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) {
327 pch_spi_handler_sub(data, reg_spsr_val, io_remap_addr);
328 ret = IRQ_HANDLED;
329 }
330
331 dev_dbg(&board_dat->pdev->dev, "%s EXIT return value=%d\n",
332 __func__, ret);
333
334 return ret;
335}
336
337/**
338 * pch_spi_set_baud_rate() - Sets SPBR field in SPBRR
339 * @master: Pointer to struct spi_master.
340 * @speed_hz: Baud rate.
341 */
342static void pch_spi_set_baud_rate(struct spi_master *master, u32 speed_hz)
343{
Grant Likely65308c42010-09-29 17:31:34 +0900344 u32 n_spbr = PCH_CLOCK_HZ / (speed_hz * 2);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600345
346 /* if baud rate is less than we can support limit it */
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600347 if (n_spbr > PCH_MAX_SPBR)
348 n_spbr = PCH_MAX_SPBR;
349
350 pch_spi_setclr_reg(master, PCH_SPBRR, n_spbr, ~MASK_SPBRR_SPBR_BITS);
351}
352
353/**
354 * pch_spi_set_bits_per_word() - Sets SIZE field in SPBRR
355 * @master: Pointer to struct spi_master.
356 * @bits_per_word: Bits per word for SPI transfer.
357 */
358static void pch_spi_set_bits_per_word(struct spi_master *master,
359 u8 bits_per_word)
360{
361 if (bits_per_word == 8)
362 pch_spi_setclr_reg(master, PCH_SPBRR, 0, SPBRR_SIZE_BIT);
363 else
364 pch_spi_setclr_reg(master, PCH_SPBRR, SPBRR_SIZE_BIT, 0);
365}
366
367/**
368 * pch_spi_setup_transfer() - Configures the PCH SPI hardware for transfer
369 * @spi: Pointer to struct spi_device.
370 */
371static void pch_spi_setup_transfer(struct spi_device *spi)
372{
Grant Likely65308c42010-09-29 17:31:34 +0900373 u32 flags = 0;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600374
375 dev_dbg(&spi->dev, "%s SPBRR content =%x setting baud rate=%d\n",
376 __func__, pch_spi_readreg(spi->master, PCH_SPBRR),
377 spi->max_speed_hz);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600378 pch_spi_set_baud_rate(spi->master, spi->max_speed_hz);
379
380 /* set bits per word */
381 pch_spi_set_bits_per_word(spi->master, spi->bits_per_word);
382
Grant Likely65308c42010-09-29 17:31:34 +0900383 if (!(spi->mode & SPI_LSB_FIRST))
384 flags |= SPCR_LSBF_BIT;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600385 if (spi->mode & SPI_CPOL)
Grant Likely65308c42010-09-29 17:31:34 +0900386 flags |= SPCR_CPOL_BIT;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600387 if (spi->mode & SPI_CPHA)
Grant Likely65308c42010-09-29 17:31:34 +0900388 flags |= SPCR_CPHA_BIT;
389 pch_spi_setclr_reg(spi->master, PCH_SPCR, flags,
390 (SPCR_LSBF_BIT | SPCR_CPOL_BIT | SPCR_CPHA_BIT));
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600391
392 /* Clear the FIFO by toggling FICLR to 1 and back to 0 */
393 pch_spi_clear_fifo(spi->master);
394}
395
396/**
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600397 * pch_spi_reset() - Clears SPI registers
398 * @master: Pointer to struct spi_master.
399 */
400static void pch_spi_reset(struct spi_master *master)
401{
402 /* write 1 to reset SPI */
403 pch_spi_writereg(master, PCH_SRST, 0x1);
404
405 /* clear reset */
406 pch_spi_writereg(master, PCH_SRST, 0x0);
407}
408
409static int pch_spi_setup(struct spi_device *pspi)
410{
411 /* check bits per word */
Grant Likely65308c42010-09-29 17:31:34 +0900412 if (pspi->bits_per_word == 0) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600413 pspi->bits_per_word = 8;
414 dev_dbg(&pspi->dev, "%s 8 bits per word\n", __func__);
415 }
416
Grant Likely65308c42010-09-29 17:31:34 +0900417 if ((pspi->bits_per_word != 8) && (pspi->bits_per_word != 16)) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600418 dev_err(&pspi->dev, "%s Invalid bits per word\n", __func__);
419 return -EINVAL;
420 }
421
422 /* Check baud rate setting */
423 /* if baud rate of chip is greater than
424 max we can support,return error */
425 if ((pspi->max_speed_hz) > PCH_MAX_BAUDRATE)
426 pspi->max_speed_hz = PCH_MAX_BAUDRATE;
427
428 dev_dbg(&pspi->dev, "%s MODE = %x\n", __func__,
Grant Likely65308c42010-09-29 17:31:34 +0900429 (pspi->mode) & (SPI_CPOL | SPI_CPHA));
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600430
431 return 0;
432}
433
434static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
435{
436
437 struct spi_transfer *transfer;
438 struct pch_spi_data *data = spi_master_get_devdata(pspi->master);
439 int retval;
440 unsigned long flags;
441
442 /* validate spi message and baud rate */
Grant Likely65308c42010-09-29 17:31:34 +0900443 if (unlikely(list_empty(&pmsg->transfers) == 1)) {
444 dev_err(&pspi->dev, "%s list empty\n", __func__);
445 retval = -EINVAL;
446 goto err_out;
447 }
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600448
Grant Likely65308c42010-09-29 17:31:34 +0900449 if (unlikely(pspi->max_speed_hz == 0)) {
450 dev_err(&pspi->dev, "%s pch_spi_tranfer maxspeed=%d\n",
451 __func__, pspi->max_speed_hz);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600452 retval = -EINVAL;
453 goto err_out;
454 }
455
456 dev_dbg(&pspi->dev, "%s Transfer List not empty. "
457 "Transfer Speed is set.\n", __func__);
458
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600459 /* validate Tx/Rx buffers and Transfer length */
460 list_for_each_entry(transfer, &pmsg->transfers, transfer_list) {
Grant Likely65308c42010-09-29 17:31:34 +0900461 if (!transfer->tx_buf && !transfer->rx_buf) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600462 dev_err(&pspi->dev,
463 "%s Tx and Rx buffer NULL\n", __func__);
464 retval = -EINVAL;
Grant Likely65308c42010-09-29 17:31:34 +0900465 goto err_out;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600466 }
467
Grant Likely65308c42010-09-29 17:31:34 +0900468 if (!transfer->len) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600469 dev_err(&pspi->dev, "%s Transfer length invalid\n",
470 __func__);
471 retval = -EINVAL;
Grant Likely65308c42010-09-29 17:31:34 +0900472 goto err_out;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600473 }
474
475 dev_dbg(&pspi->dev, "%s Tx/Rx buffer valid. Transfer length"
476 " valid\n", __func__);
477
478 /* if baud rate hs been specified validate the same */
Grant Likely65308c42010-09-29 17:31:34 +0900479 if (transfer->speed_hz > PCH_MAX_BAUDRATE)
480 transfer->speed_hz = PCH_MAX_BAUDRATE;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600481
482 /* if bits per word has been specified validate the same */
483 if (transfer->bits_per_word) {
484 if ((transfer->bits_per_word != 8)
485 && (transfer->bits_per_word != 16)) {
486 retval = -EINVAL;
487 dev_err(&pspi->dev,
488 "%s Invalid bits per word\n", __func__);
Grant Likely65308c42010-09-29 17:31:34 +0900489 goto err_out;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600490 }
491 }
492 }
493
Grant Likely65308c42010-09-29 17:31:34 +0900494 spin_lock_irqsave(&data->lock, flags);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600495
Grant Likely65308c42010-09-29 17:31:34 +0900496 /* We won't process any messages if we have been asked to terminate */
497 if (data->status == STATUS_EXITING) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600498 dev_err(&pspi->dev, "%s status = STATUS_EXITING.\n", __func__);
499 retval = -ESHUTDOWN;
500 goto err_return_spinlock;
501 }
502
503 /* If suspended ,return -EINVAL */
504 if (data->board_dat->suspend_sts) {
Grant Likely65308c42010-09-29 17:31:34 +0900505 dev_err(&pspi->dev, "%s suspend; returning EINVAL\n", __func__);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600506 retval = -EINVAL;
507 goto err_return_spinlock;
508 }
509
510 /* set status of message */
511 pmsg->actual_length = 0;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600512 dev_dbg(&pspi->dev, "%s - pmsg->status =%d\n", __func__, pmsg->status);
513
514 pmsg->status = -EINPROGRESS;
515
516 /* add message to queue */
517 list_add_tail(&pmsg->queue, &data->queue);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600518 dev_dbg(&pspi->dev, "%s - Invoked list_add_tail\n", __func__);
519
520 /* schedule work queue to run */
521 queue_work(data->wk, &data->work);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600522 dev_dbg(&pspi->dev, "%s - Invoked queue work\n", __func__);
523
524 retval = 0;
525
526err_return_spinlock:
527 spin_unlock_irqrestore(&data->lock, flags);
528err_out:
529 dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval);
530 return retval;
531}
532
533static inline void pch_spi_select_chip(struct pch_spi_data *data,
534 struct spi_device *pspi)
535{
Grant Likely65308c42010-09-29 17:31:34 +0900536 if (data->current_chip != NULL) {
537 if (pspi->chip_select != data->n_curnt_chip) {
538 dev_dbg(&pspi->dev, "%s : different slave\n", __func__);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600539 data->current_chip = NULL;
540 }
541 }
542
543 data->current_chip = pspi;
544
545 data->n_curnt_chip = data->current_chip->chip_select;
546
547 dev_dbg(&pspi->dev, "%s :Invoking pch_spi_setup_transfer\n", __func__);
548 pch_spi_setup_transfer(pspi);
549}
550
551static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw,
Grant Likely65308c42010-09-29 17:31:34 +0900552 struct spi_message **ppmsg)
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600553{
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600554 int size;
555 u32 n_writes;
556 int j;
557 struct spi_message *pmsg;
558 const u8 *tx_buf;
559 const u16 *tx_sbuf;
560
561 pmsg = *ppmsg;
562
563 /* set baud rate if needed */
564 if (data->cur_trans->speed_hz) {
Grant Likely65308c42010-09-29 17:31:34 +0900565 dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__);
566 pch_spi_set_baud_rate(data->master, data->cur_trans->speed_hz);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600567 }
568
569 /* set bits per word if needed */
Grant Likely65308c42010-09-29 17:31:34 +0900570 if (data->cur_trans->bits_per_word &&
571 (data->current_msg->spi->bits_per_word != data->cur_trans->bits_per_word)) {
572 dev_dbg(&data->master->dev, "%s:set bits per word\n", __func__);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600573 pch_spi_set_bits_per_word(data->master,
Grant Likely65308c42010-09-29 17:31:34 +0900574 data->cur_trans->bits_per_word);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600575 *bpw = data->cur_trans->bits_per_word;
576 } else {
577 *bpw = data->current_msg->spi->bits_per_word;
578 }
579
580 /* reset Tx/Rx index */
581 data->tx_index = 0;
582 data->rx_index = 0;
583
584 data->bpw_len = data->cur_trans->len / (*bpw / 8);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600585
586 /* find alloc size */
Grant Likely65308c42010-09-29 17:31:34 +0900587 size = data->cur_trans->len * sizeof(*data->pkt_tx_buff);
588
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600589 /* allocate memory for pkt_tx_buff & pkt_rx_buffer */
590 data->pkt_tx_buff = kzalloc(size, GFP_KERNEL);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600591 if (data->pkt_tx_buff != NULL) {
592 data->pkt_rx_buff = kzalloc(size, GFP_KERNEL);
Grant Likely65308c42010-09-29 17:31:34 +0900593 if (!data->pkt_rx_buff)
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600594 kfree(data->pkt_tx_buff);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600595 }
596
Grant Likely65308c42010-09-29 17:31:34 +0900597 if (!data->pkt_rx_buff) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600598 /* flush queue and set status of all transfers to -ENOMEM */
Grant Likely65308c42010-09-29 17:31:34 +0900599 dev_err(&data->master->dev, "%s :kzalloc failed\n", __func__);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600600 list_for_each_entry(pmsg, data->queue.next, queue) {
601 pmsg->status = -ENOMEM;
602
603 if (pmsg->complete != 0)
604 pmsg->complete(pmsg->context);
605
606 /* delete from queue */
607 list_del_init(&pmsg->queue);
608 }
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600609 return;
610 }
611
612 /* copy Tx Data */
Grant Likely65308c42010-09-29 17:31:34 +0900613 if (data->cur_trans->tx_buf != NULL) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600614 if (*bpw == 8) {
Grant Likely65308c42010-09-29 17:31:34 +0900615 tx_buf = data->cur_trans->tx_buf;
616 for (j = 0; j < data->bpw_len; j++)
617 data->pkt_tx_buff[j] = *tx_buf++;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600618 } else {
Grant Likely65308c42010-09-29 17:31:34 +0900619 tx_sbuf = data->cur_trans->tx_buf;
620 for (j = 0; j < data->bpw_len; j++)
621 data->pkt_tx_buff[j] = *tx_sbuf++;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600622 }
623 }
624
625 /* if len greater than PCH_MAX_FIFO_DEPTH, write 16,else len bytes */
Grant Likely65308c42010-09-29 17:31:34 +0900626 n_writes = data->bpw_len;
627 if (n_writes > PCH_MAX_FIFO_DEPTH)
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600628 n_writes = PCH_MAX_FIFO_DEPTH;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600629
Grant Likely65308c42010-09-29 17:31:34 +0900630 dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing "
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600631 "0x2 to SSNXCR\n", __func__);
632 pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW);
633
Grant Likely65308c42010-09-29 17:31:34 +0900634 for (j = 0; j < n_writes; j++)
635 pch_spi_writereg(data->master, PCH_SPDWR, data->pkt_tx_buff[j]);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600636
637 /* update tx_index */
638 data->tx_index = j;
639
640 /* reset transfer complete flag */
641 data->transfer_complete = false;
642 data->transfer_active = true;
643}
644
645
646static void pch_spi_nomore_transfer(struct pch_spi_data *data,
647 struct spi_message *pmsg)
648{
Grant Likely65308c42010-09-29 17:31:34 +0900649 dev_dbg(&data->master->dev, "%s called\n", __func__);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600650 /* Invoke complete callback
Grant Likely65308c42010-09-29 17:31:34 +0900651 * [To the spi core..indicating end of transfer] */
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600652 data->current_msg->status = 0;
653
Grant Likely65308c42010-09-29 17:31:34 +0900654 if (data->current_msg->complete != 0) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600655 dev_dbg(&data->master->dev,
656 "%s:Invoking callback of SPI core\n", __func__);
657 data->current_msg->complete(data->current_msg->context);
658 }
659
660 /* update status in global variable */
661 data->bcurrent_msg_processing = false;
662
663 dev_dbg(&data->master->dev,
664 "%s:data->bcurrent_msg_processing = false\n", __func__);
665
666 data->current_msg = NULL;
667 data->cur_trans = NULL;
668
Grant Likely65308c42010-09-29 17:31:34 +0900669 /* check if we have items in list and not suspending
670 * return 1 if list empty */
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600671 if ((list_empty(&data->queue) == 0) &&
Grant Likely65308c42010-09-29 17:31:34 +0900672 (!data->board_dat->suspend_sts) &&
673 (data->status != STATUS_EXITING)) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600674 /* We have some more work to do (either there is more tranint
Grant Likely65308c42010-09-29 17:31:34 +0900675 * bpw;sfer requests in the current message or there are
676 *more messages)
677 */
678 dev_dbg(&data->master->dev, "%s:Invoke queue_work\n", __func__);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600679 queue_work(data->wk, &data->work);
Grant Likely65308c42010-09-29 17:31:34 +0900680 } else if (data->board_dat->suspend_sts ||
681 data->status == STATUS_EXITING) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600682 dev_dbg(&data->master->dev,
683 "%s suspend/remove initiated, flushing queue\n",
684 __func__);
685 list_for_each_entry(pmsg, data->queue.next, queue) {
686 pmsg->status = -EIO;
687
Grant Likely65308c42010-09-29 17:31:34 +0900688 if (pmsg->complete)
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600689 pmsg->complete(pmsg->context);
690
691 /* delete from queue */
692 list_del_init(&pmsg->queue);
693 }
694 }
695}
696
697static void pch_spi_set_ir(struct pch_spi_data *data)
698{
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600699 /* enable interrupts */
700 if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH) {
Justin P. Mattock77e58ef2010-12-31 09:50:31 -0800701 /* set receive threshold to PCH_RX_THOLD */
Grant Likely65308c42010-09-29 17:31:34 +0900702 pch_spi_setclr_reg(data->master, PCH_SPCR,
Tomoya MORINAGA9d32af62010-12-24 11:40:50 +0900703 PCH_RX_THOLD << SPCR_RFIC_FIELD,
704 ~MASK_RFIC_SPCR_BITS);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600705 /* enable FI and RFI interrupts */
Grant Likely65308c42010-09-29 17:31:34 +0900706 pch_spi_setclr_reg(data->master, PCH_SPCR,
Tomoya MORINAGA9d32af62010-12-24 11:40:50 +0900707 SPCR_RFIE_BIT | SPCR_FIE_BIT, 0);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600708 } else {
Justin P. Mattock77e58ef2010-12-31 09:50:31 -0800709 /* set receive threshold to maximum */
Grant Likely65308c42010-09-29 17:31:34 +0900710 pch_spi_setclr_reg(data->master, PCH_SPCR,
711 PCH_RX_THOLD_MAX << SPCR_TFIC_FIELD,
712 ~MASK_TFIC_SPCR_BITS);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600713 /* enable FI interrupt */
Grant Likely65308c42010-09-29 17:31:34 +0900714 pch_spi_setclr_reg(data->master, PCH_SPCR, SPCR_FIE_BIT, 0);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600715 }
716
717 dev_dbg(&data->master->dev,
718 "%s:invoking pch_spi_set_enable to enable SPI\n", __func__);
719
720 /* SPI set enable */
Grant Likely65308c42010-09-29 17:31:34 +0900721 pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, SPCR_SPE_BIT, 0);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600722
723 /* Wait until the transfer completes; go to sleep after
724 initiating the transfer. */
725 dev_dbg(&data->master->dev,
726 "%s:waiting for transfer to get over\n", __func__);
727
728 wait_event_interruptible(data->wait, data->transfer_complete);
729
730 pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL);
731 dev_dbg(&data->master->dev,
732 "%s:no more control over SSN-writing 0 to SSNXCR.", __func__);
733
734 data->transfer_active = false;
735 dev_dbg(&data->master->dev,
736 "%s set data->transfer_active = false\n", __func__);
737
738 /* clear all interrupts */
739 pch_spi_writereg(data->master, PCH_SPSR,
Grant Likely65308c42010-09-29 17:31:34 +0900740 pch_spi_readreg(data->master, PCH_SPSR));
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600741 /* disable interrupts */
Grant Likely65308c42010-09-29 17:31:34 +0900742 pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600743}
744
745static void pch_spi_copy_rx_data(struct pch_spi_data *data, int bpw)
746{
747 int j;
748 u8 *rx_buf;
749 u16 *rx_sbuf;
750
751 /* copy Rx Data */
Grant Likely65308c42010-09-29 17:31:34 +0900752 if (!data->cur_trans->rx_buf)
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600753 return;
754
755 if (bpw == 8) {
Grant Likely65308c42010-09-29 17:31:34 +0900756 rx_buf = data->cur_trans->rx_buf;
757 for (j = 0; j < data->bpw_len; j++)
758 *rx_buf++ = data->pkt_rx_buff[j] & 0xFF;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600759 } else {
Grant Likely65308c42010-09-29 17:31:34 +0900760 rx_sbuf = data->cur_trans->rx_buf;
761 for (j = 0; j < data->bpw_len; j++)
762 *rx_sbuf++ = data->pkt_rx_buff[j];
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600763 }
764}
765
766
767static void pch_spi_process_messages(struct work_struct *pwork)
768{
769 struct spi_message *pmsg;
Grant Likely65308c42010-09-29 17:31:34 +0900770 struct pch_spi_data *data;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600771 int bpw;
772
Grant Likely65308c42010-09-29 17:31:34 +0900773 data = container_of(pwork, struct pch_spi_data, work);
Grant Likely8e41b522010-10-13 23:03:15 -0600774 dev_dbg(&data->master->dev, "%s data initialized\n", __func__);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600775
776 spin_lock(&data->lock);
777
778 /* check if suspend has been initiated;if yes flush queue */
Grant Likely65308c42010-09-29 17:31:34 +0900779 if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600780 dev_dbg(&data->master->dev,
781 "%s suspend/remove initiated,flushing queue\n",
782 __func__);
Grant Likely65308c42010-09-29 17:31:34 +0900783
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600784 list_for_each_entry(pmsg, data->queue.next, queue) {
785 pmsg->status = -EIO;
786
787 if (pmsg->complete != 0) {
788 spin_unlock(&data->lock);
789 pmsg->complete(pmsg->context);
790 spin_lock(&data->lock);
791 }
792
793 /* delete from queue */
794 list_del_init(&pmsg->queue);
795 }
796
797 spin_unlock(&data->lock);
798 return;
799 }
800
801 data->bcurrent_msg_processing = true;
802 dev_dbg(&data->master->dev,
803 "%s Set data->bcurrent_msg_processing= true\n", __func__);
804
805 /* Get the message from the queue and delete it from there. */
Grant Likely65308c42010-09-29 17:31:34 +0900806 data->current_msg = list_entry(data->queue.next, struct spi_message,
807 queue);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600808
809 list_del_init(&data->current_msg->queue);
810
811 data->current_msg->status = 0;
812
813 pch_spi_select_chip(data, data->current_msg->spi);
814
815 spin_unlock(&data->lock);
816
817 do {
818 /* If we are already processing a message get the next
819 transfer structure from the message otherwise retrieve
820 the 1st transfer request from the message. */
821 spin_lock(&data->lock);
822
823 if (data->cur_trans == NULL) {
824 data->cur_trans =
825 list_entry(data->current_msg->transfers.
826 next, struct spi_transfer,
827 transfer_list);
828 dev_dbg(&data->master->dev,
829 "%s :Getting 1st transfer message\n", __func__);
830 } else {
831 data->cur_trans =
832 list_entry(data->cur_trans->transfer_list.next,
833 struct spi_transfer,
834 transfer_list);
835 dev_dbg(&data->master->dev,
836 "%s :Getting next transfer message\n",
837 __func__);
838 }
839
840 spin_unlock(&data->lock);
841
842 pch_spi_set_tx(data, &bpw, &pmsg);
843
844 /* Control interrupt*/
845 pch_spi_set_ir(data);
846
847 /* Disable SPI transfer */
848 pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, 0,
849 SPCR_SPE_BIT);
850
851 /* clear FIFO */
852 pch_spi_clear_fifo(data->master);
853
854 /* copy Rx Data */
855 pch_spi_copy_rx_data(data, bpw);
856
857 /* free memory */
858 kfree(data->pkt_rx_buff);
859 data->pkt_rx_buff = NULL;
860
861 kfree(data->pkt_tx_buff);
862 data->pkt_tx_buff = NULL;
863
864 /* increment message count */
865 data->current_msg->actual_length += data->cur_trans->len;
866
867 dev_dbg(&data->master->dev,
868 "%s:data->current_msg->actual_length=%d\n",
869 __func__, data->current_msg->actual_length);
870
871 /* check for delay */
872 if (data->cur_trans->delay_usecs) {
873 dev_dbg(&data->master->dev, "%s:"
874 "delay in usec=%d\n", __func__,
875 data->cur_trans->delay_usecs);
876 udelay(data->cur_trans->delay_usecs);
877 }
878
879 spin_lock(&data->lock);
880
881 /* No more transfer in this message. */
882 if ((data->cur_trans->transfer_list.next) ==
883 &(data->current_msg->transfers)) {
884 pch_spi_nomore_transfer(data, pmsg);
885 }
886
887 spin_unlock(&data->lock);
888
Grant Likely65308c42010-09-29 17:31:34 +0900889 } while (data->cur_trans != NULL);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600890}
891
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900892static void pch_spi_free_resources(struct pch_spi_board_data *board_dat,
893 struct pch_spi_data *data)
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600894{
895 dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
896
897 /* free workqueue */
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900898 if (data->wk != NULL) {
899 destroy_workqueue(data->wk);
900 data->wk = NULL;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600901 dev_dbg(&board_dat->pdev->dev,
902 "%s destroy_workqueue invoked successfully\n",
903 __func__);
904 }
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600905}
906
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900907static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
908 struct pch_spi_data *data)
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600909{
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900910 int retval = 0;
911
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600912 dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
913
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600914 /* create workqueue */
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900915 data->wk = create_singlethread_workqueue(KBUILD_MODNAME);
916 if (!data->wk) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600917 dev_err(&board_dat->pdev->dev,
918 "%s create_singlet hread_workqueue failed\n", __func__);
919 retval = -EBUSY;
920 goto err_return;
921 }
922
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600923 /* reset PCH SPI h/w */
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900924 pch_spi_reset(data->master);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600925 dev_dbg(&board_dat->pdev->dev,
926 "%s pch_spi_reset invoked successfully\n", __func__);
927
Grant Likely65308c42010-09-29 17:31:34 +0900928 dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600929
930err_return:
931 if (retval != 0) {
932 dev_err(&board_dat->pdev->dev,
933 "%s FAIL:invoking pch_spi_free_resources\n", __func__);
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900934 pch_spi_free_resources(board_dat, data);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600935 }
936
937 dev_dbg(&board_dat->pdev->dev, "%s Return=%d\n", __func__, retval);
938
939 return retval;
940}
941
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900942static int __devinit pch_spi_pd_probe(struct platform_device *plat_dev)
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600943{
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900944 int ret;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600945 struct spi_master *master;
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900946 struct pch_spi_board_data *board_dat = dev_get_platdata(&plat_dev->dev);
947 struct pch_spi_data *data;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600948
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900949 master = spi_alloc_master(&board_dat->pdev->dev,
950 sizeof(struct pch_spi_data));
951 if (!master) {
952 dev_err(&plat_dev->dev, "spi_alloc_master[%d] failed.\n",
953 plat_dev->id);
954 return -ENOMEM;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600955 }
956
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900957 data = spi_master_get_devdata(master);
958 data->master = master;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600959
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900960 platform_set_drvdata(plat_dev, data);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600961
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900962 /* baseaddress + 0x20(offset) */
963 data->io_remap_addr = pci_iomap(board_dat->pdev, 1, 0) +
964 0x20 * plat_dev->id;
965 if (!data->io_remap_addr) {
966 dev_err(&plat_dev->dev, "%s pci_iomap failed\n", __func__);
967 ret = -ENOMEM;
968 goto err_pci_iomap;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600969 }
970
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900971 dev_dbg(&plat_dev->dev, "[ch%d] remap_addr=%p\n",
972 plat_dev->id, data->io_remap_addr);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600973
974 /* initialize members of SPI master */
975 master->bus_num = -1;
976 master->num_chipselect = PCH_MAX_CS;
977 master->setup = pch_spi_setup;
978 master->transfer = pch_spi_transfer;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600979
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900980 data->board_dat = board_dat;
981 data->plat_dev = plat_dev;
982 data->n_curnt_chip = 255;
983 data->status = STATUS_RUNNING;
984 data->ch = plat_dev->id;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600985
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900986 INIT_LIST_HEAD(&data->queue);
987 spin_lock_init(&data->lock);
988 INIT_WORK(&data->work, pch_spi_process_messages);
989 init_waitqueue_head(&data->wait);
Grant Likely65308c42010-09-29 17:31:34 +0900990
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900991 ret = pch_spi_get_resources(board_dat, data);
992 if (ret) {
993 dev_err(&plat_dev->dev, "%s fail(retval=%d)\n", __func__, ret);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -0600994 goto err_spi_get_resources;
995 }
996
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +0900997 ret = request_irq(board_dat->pdev->irq, pch_spi_handler,
998 IRQF_SHARED, KBUILD_MODNAME, data);
999 if (ret) {
1000 dev_err(&plat_dev->dev,
1001 "%s request_irq failed\n", __func__);
1002 goto err_request_irq;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001003 }
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001004 data->irq_reg_sts = true;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001005
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001006 pch_spi_set_master_mode(master);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001007
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001008 ret = spi_register_master(master);
1009 if (ret != 0) {
1010 dev_err(&plat_dev->dev,
1011 "%s spi_register_master FAILED\n", __func__);
1012 goto err_spi_register_master;
1013 }
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001014
1015 return 0;
1016
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001017err_spi_register_master:
1018 free_irq(board_dat->pdev->irq, board_dat);
1019err_request_irq:
1020 pch_spi_free_resources(board_dat, data);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001021err_spi_get_resources:
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001022 pci_iounmap(board_dat->pdev, data->io_remap_addr);
1023err_pci_iomap:
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001024 spi_master_put(master);
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001025
1026 return ret;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001027}
1028
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001029static int __devexit pch_spi_pd_remove(struct platform_device *plat_dev)
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001030{
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001031 struct pch_spi_board_data *board_dat = dev_get_platdata(&plat_dev->dev);
1032 struct pch_spi_data *data = platform_get_drvdata(plat_dev);
Grant Likely65308c42010-09-29 17:31:34 +09001033 int count;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001034
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001035 dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n",
1036 __func__, plat_dev->id, board_dat->pdev->irq);
Grant Likely65308c42010-09-29 17:31:34 +09001037 /* check for any pending messages; no action is taken if the queue
1038 * is still full; but at least we tried. Unload anyway */
1039 count = 500;
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001040 spin_lock(&data->lock);
1041 data->status = STATUS_EXITING;
1042 while ((list_empty(&data->queue) == 0) && --count) {
Grant Likely65308c42010-09-29 17:31:34 +09001043 dev_dbg(&board_dat->pdev->dev, "%s :queue not empty\n",
1044 __func__);
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001045 spin_unlock(&data->lock);
Grant Likely65308c42010-09-29 17:31:34 +09001046 msleep(PCH_SLEEP_TIME);
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001047 spin_lock(&data->lock);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001048 }
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001049 spin_unlock(&data->lock);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001050
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001051 pch_spi_free_resources(board_dat, data);
1052 /* disable interrupts & free IRQ */
1053 if (data->irq_reg_sts) {
1054 /* disable interrupts */
1055 pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
1056 data->irq_reg_sts = false;
1057 free_irq(board_dat->pdev->irq, data);
1058 }
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001059
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001060 pci_iounmap(board_dat->pdev, data->io_remap_addr);
1061 spi_unregister_master(data->master);
1062 spi_master_put(data->master);
1063 platform_set_drvdata(plat_dev, NULL);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001064
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001065 return 0;
1066}
1067#ifdef CONFIG_PM
1068static int pch_spi_pd_suspend(struct platform_device *pd_dev,
1069 pm_message_t state)
1070{
1071 u8 count;
1072 struct pch_spi_board_data *board_dat = dev_get_platdata(&pd_dev->dev);
1073 struct pch_spi_data *data = platform_get_drvdata(pd_dev);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001074
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001075 dev_dbg(&pd_dev->dev, "%s ENTRY\n", __func__);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001076
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001077 if (!board_dat) {
1078 dev_err(&pd_dev->dev,
1079 "%s pci_get_drvdata returned NULL\n", __func__);
1080 return -EFAULT;
1081 }
1082
1083 /* check if the current message is processed:
1084 Only after thats done the transfer will be suspended */
1085 count = 255;
1086 while ((--count) > 0)
1087 if (!(data->bcurrent_msg_processing)) {
1088 break;
1089 msleep(PCH_SLEEP_TIME);
1090 }
1091
1092 /* Free IRQ */
1093 if (data->irq_reg_sts) {
1094 /* disable all interrupts */
1095 pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
1096 pch_spi_reset(data->master);
1097 free_irq(board_dat->pdev->irq, data);
1098
1099 data->irq_reg_sts = false;
1100 dev_dbg(&pd_dev->dev,
1101 "%s free_irq invoked successfully.\n", __func__);
1102 }
1103
1104 return 0;
1105}
1106
1107static int pch_spi_pd_resume(struct platform_device *pd_dev)
1108{
1109 struct pch_spi_board_data *board_dat = dev_get_platdata(&pd_dev->dev);
1110 struct pch_spi_data *data = platform_get_drvdata(pd_dev);
1111 int retval;
1112
1113 if (!board_dat) {
1114 dev_err(&pd_dev->dev,
1115 "%s pci_get_drvdata returned NULL\n", __func__);
1116 return -EFAULT;
1117 }
1118
1119 if (!data->irq_reg_sts) {
1120 /* register IRQ */
1121 retval = request_irq(board_dat->pdev->irq, pch_spi_handler,
1122 IRQF_SHARED, KBUILD_MODNAME, data);
1123 if (retval < 0) {
1124 dev_err(&pd_dev->dev,
1125 "%s request_irq failed\n", __func__);
1126 return retval;
1127 }
1128
1129 /* reset PCH SPI h/w */
1130 pch_spi_reset(data->master);
1131 pch_spi_set_master_mode(data->master);
1132 data->irq_reg_sts = true;
1133 }
1134 return 0;
1135}
1136#else
1137#define pch_spi_pd_suspend NULL
1138#define pch_spi_pd_resume NULL
1139#endif
1140
1141static struct platform_driver pch_spi_pd_driver = {
1142 .driver = {
1143 .name = "pch-spi",
1144 .owner = THIS_MODULE,
1145 },
1146 .probe = pch_spi_pd_probe,
1147 .remove = __devexit_p(pch_spi_pd_remove),
1148 .suspend = pch_spi_pd_suspend,
1149 .resume = pch_spi_pd_resume
1150};
1151
1152static int __devinit pch_spi_probe(struct pci_dev *pdev,
1153 const struct pci_device_id *id)
1154{
1155 struct pch_spi_board_data *board_dat;
1156 struct platform_device *pd_dev = NULL;
1157 int retval;
1158 int i;
1159 struct pch_pd_dev_save *pd_dev_save;
1160
1161 pd_dev_save = kzalloc(sizeof(struct pch_pd_dev_save), GFP_KERNEL);
1162 if (!pd_dev_save) {
1163 dev_err(&pdev->dev, "%s Can't allocate pd_dev_sav\n", __func__);
1164 return -ENOMEM;
1165 }
1166
1167 board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL);
1168 if (!board_dat) {
1169 dev_err(&pdev->dev, "%s Can't allocate board_dat\n", __func__);
1170 retval = -ENOMEM;
1171 goto err_no_mem;
1172 }
1173
1174 retval = pci_request_regions(pdev, KBUILD_MODNAME);
1175 if (retval) {
1176 dev_err(&pdev->dev, "%s request_region failed\n", __func__);
1177 goto pci_request_regions;
1178 }
1179
1180 board_dat->pdev = pdev;
1181 board_dat->num = id->driver_data;
1182 pd_dev_save->num = id->driver_data;
1183 pd_dev_save->board_dat = board_dat;
1184
1185 retval = pci_enable_device(pdev);
1186 if (retval) {
1187 dev_err(&pdev->dev, "%s pci_enable_device failed\n", __func__);
1188 goto pci_enable_device;
1189 }
1190
1191 for (i = 0; i < board_dat->num; i++) {
1192 pd_dev = platform_device_alloc("pch-spi", i);
1193 if (!pd_dev) {
1194 dev_err(&pdev->dev, "platform_device_alloc failed\n");
1195 goto err_platform_device;
1196 }
1197 pd_dev_save->pd_save[i] = pd_dev;
1198 pd_dev->dev.parent = &pdev->dev;
1199
1200 retval = platform_device_add_data(pd_dev, board_dat,
1201 sizeof(*board_dat));
1202 if (retval) {
1203 dev_err(&pdev->dev,
1204 "platform_device_add_data failed\n");
1205 platform_device_put(pd_dev);
1206 goto err_platform_device;
1207 }
1208
1209 retval = platform_device_add(pd_dev);
1210 if (retval) {
1211 dev_err(&pdev->dev, "platform_device_add failed\n");
1212 platform_device_put(pd_dev);
1213 goto err_platform_device;
1214 }
1215 }
1216
1217 pci_set_drvdata(pdev, pd_dev_save);
1218
1219 return 0;
1220
1221err_platform_device:
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001222 pci_disable_device(pdev);
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001223pci_enable_device:
1224 pci_release_regions(pdev);
1225pci_request_regions:
1226 kfree(board_dat);
1227err_no_mem:
1228 kfree(pd_dev_save);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001229
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001230 return retval;
1231}
1232
1233static void __devexit pch_spi_remove(struct pci_dev *pdev)
1234{
1235 int i;
1236 struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
1237
1238 dev_dbg(&pdev->dev, "%s ENTRY:pdev=%p\n", __func__, pdev);
1239
1240 for (i = 0; i < pd_dev_save->num; i++)
1241 platform_device_unregister(pd_dev_save->pd_save[i]);
1242
1243 pci_disable_device(pdev);
1244 pci_release_regions(pdev);
1245 kfree(pd_dev_save->board_dat);
1246 kfree(pd_dev_save);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001247}
1248
1249#ifdef CONFIG_PM
1250static int pch_spi_suspend(struct pci_dev *pdev, pm_message_t state)
1251{
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001252 int retval;
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001253 struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001254
1255 dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
1256
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001257 pd_dev_save->board_dat->suspend_sts = true;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001258
1259 /* save config space */
1260 retval = pci_save_state(pdev);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001261 if (retval == 0) {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001262 pci_enable_wake(pdev, PCI_D3hot, 0);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001263 pci_disable_device(pdev);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001264 pci_set_power_state(pdev, PCI_D3hot);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001265 } else {
1266 dev_err(&pdev->dev, "%s pci_save_state failed\n", __func__);
1267 }
1268
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001269 return retval;
1270}
1271
1272static int pch_spi_resume(struct pci_dev *pdev)
1273{
1274 int retval;
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001275 struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001276 dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
1277
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001278 pci_set_power_state(pdev, PCI_D0);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001279 pci_restore_state(pdev);
1280
1281 retval = pci_enable_device(pdev);
1282 if (retval < 0) {
1283 dev_err(&pdev->dev,
1284 "%s pci_enable_device failed\n", __func__);
1285 } else {
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001286 pci_enable_wake(pdev, PCI_D3hot, 0);
1287
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001288 /* set suspend status to false */
1289 pd_dev_save->board_dat->suspend_sts = false;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001290 }
1291
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001292 return retval;
1293}
1294#else
1295#define pch_spi_suspend NULL
1296#define pch_spi_resume NULL
1297
1298#endif
1299
1300static struct pci_driver pch_spi_pcidev = {
1301 .name = "pch_spi",
1302 .id_table = pch_spi_pcidev_id,
1303 .probe = pch_spi_probe,
1304 .remove = pch_spi_remove,
1305 .suspend = pch_spi_suspend,
1306 .resume = pch_spi_resume,
1307};
1308
1309static int __init pch_spi_init(void)
1310{
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001311 int ret;
1312 ret = platform_driver_register(&pch_spi_pd_driver);
1313 if (ret)
1314 return ret;
1315
1316 ret = pci_register_driver(&pch_spi_pcidev);
1317 if (ret)
1318 return ret;
1319
1320 return 0;
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001321}
1322module_init(pch_spi_init);
1323
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001324static void __exit pch_spi_exit(void)
1325{
1326 pci_unregister_driver(&pch_spi_pcidev);
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001327 platform_driver_unregister(&pch_spi_pd_driver);
Masayuki Ohtakee8b17b52010-10-08 12:44:49 -06001328}
1329module_exit(pch_spi_exit);
1330
1331MODULE_LICENSE("GPL");
Tomoya MORINAGAf016aeb2011-06-07 14:50:10 +09001332MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH SPI Driver");