spi-s3c24xx.c 16.3 KB
Newer Older
Grant Likely's avatar
Grant Likely committed
1
/*
2
 * Copyright (c) 2006 Ben Dooks
3
 * Copyright 2006-2009 Simtec Electronics
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
*/

#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
21
#include <linux/gpio.h>
Ben Dooks's avatar
Ben Dooks committed
22
#include <linux/io.h>
23
#include <linux/slab.h>
24 25 26

#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
27
#include <linux/spi/s3c24xx.h>
28
#include <linux/module.h>
29

30
#include <plat/regs-spi.h>
31

32 33 34
#include <plat/fiq.h>
#include <asm/fiq.h>

Grant Likely's avatar
Grant Likely committed
35
#include "spi-s3c24xx-fiq.h"
36

37 38 39 40 41 42 43 44 45 46 47 48 49 50
/**
 * s3c24xx_spi_devstate - per device data
 * @hz: Last frequency calculated for @sppre field.
 * @mode: Last mode setting for the @spcon field.
 * @spcon: Value to write to the SPCON register.
 * @sppre: Value to write to the SPPRE register.
 */
struct s3c24xx_spi_devstate {
	unsigned int	hz;
	unsigned int	mode;
	u8		spcon;
	u8		sppre;
};

51 52 53 54 55 56 57
enum spi_fiq_mode {
	FIQ_MODE_NONE	= 0,
	FIQ_MODE_TX	= 1,
	FIQ_MODE_RX	= 2,
	FIQ_MODE_TXRX	= 3,
};

58 59 60 61 62 63 64 65 66 67
struct s3c24xx_spi {
	/* bitbang has to be first */
	struct spi_bitbang	 bitbang;
	struct completion	 done;

	void __iomem		*regs;
	int			 irq;
	int			 len;
	int			 count;

68 69 70 71 72
	struct fiq_handler	 fiq_handler;
	enum spi_fiq_mode	 fiq_mode;
	unsigned char		 fiq_inuse;
	unsigned char		 fiq_claimed;

73
	void			(*set_cs)(struct s3c2410_spi_info *spi,
74 75
					  int cs, int pol);

76 77 78 79 80 81 82 83 84 85 86 87
	/* data buffers */
	const unsigned char	*tx;
	unsigned char		*rx;

	struct clk		*clk;
	struct resource		*ioarea;
	struct spi_master	*master;
	struct spi_device	*curdev;
	struct device		*dev;
	struct s3c2410_spi_info *pdata;
};

88

89 90 91 92 93 94 95 96
#define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT)
#define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP)

static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev)
{
	return spi_master_get_devdata(sdev->master);
}

97 98
static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol)
{
99
	gpio_set_value(spi->pin_cs, pol);
100 101
}

102 103
static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
{
104
	struct s3c24xx_spi_devstate *cs = spi->controller_state;
105 106
	struct s3c24xx_spi *hw = to_hw(spi);
	unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
107 108

	/* change the chipselect state and the state of the spi engine clock */
109 110 111

	switch (value) {
	case BITBANG_CS_INACTIVE:
112
		hw->set_cs(hw->pdata, spi->chip_select, cspol^1);
113
		writeb(cs->spcon, hw->regs + S3C2410_SPCON);
114 115 116
		break;

	case BITBANG_CS_ACTIVE:
117 118
		writeb(cs->spcon | S3C2410_SPCON_ENSCK,
		       hw->regs + S3C2410_SPCON);
119
		hw->set_cs(hw->pdata, spi->chip_select, cspol);
120 121 122 123
		break;
	}
}

124 125
static int s3c24xx_spi_update_state(struct spi_device *spi,
				    struct spi_transfer *t)
126 127
{
	struct s3c24xx_spi *hw = to_hw(spi);
128
	struct s3c24xx_spi_devstate *cs = spi->controller_state;
129 130 131
	unsigned int bpw;
	unsigned int hz;
	unsigned int div;
132
	unsigned long clk;
133 134 135 136

	bpw = t ? t->bits_per_word : spi->bits_per_word;
	hz  = t ? t->speed_hz : spi->max_speed_hz;

137 138 139 140 141 142
	if (!bpw)
		bpw = 8;

	if (!hz)
		hz = spi->max_speed_hz;

143 144 145 146 147
	if (bpw != 8) {
		dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
		return -EINVAL;
	}

148
	if (spi->mode != cs->mode) {
149
		u8 spcon = SPCON_DEFAULT | S3C2410_SPCON_ENSCK;
150 151 152

		if (spi->mode & SPI_CPHA)
			spcon |= S3C2410_SPCON_CPHA_FMTB;
153

154 155
		if (spi->mode & SPI_CPOL)
			spcon |= S3C2410_SPCON_CPOL_HIGH;
156

157 158 159
		cs->mode = spi->mode;
		cs->spcon = spcon;
	}
160

161 162 163
	if (cs->hz != hz) {
		clk = clk_get_rate(hw->clk);
		div = DIV_ROUND_UP(clk, hz * 2) - 1;
164

165 166
		if (div > 255)
			div = 255;
167

168 169 170 171 172
		dev_dbg(&spi->dev, "pre-scaler=%d (wanted %d, got %ld)\n",
			div, hz, clk / (2 * (div + 1)));

		cs->hz = hz;
		cs->sppre = div;
173 174 175 176 177
	}

	return 0;
}

178 179 180 181 182 183 184 185 186 187 188 189 190 191
static int s3c24xx_spi_setupxfer(struct spi_device *spi,
				 struct spi_transfer *t)
{
	struct s3c24xx_spi_devstate *cs = spi->controller_state;
	struct s3c24xx_spi *hw = to_hw(spi);
	int ret;

	ret = s3c24xx_spi_update_state(spi, t);
	if (!ret)
		writeb(cs->sppre, hw->regs + S3C2410_SPPRE);

	return ret;
}

192 193
static int s3c24xx_spi_setup(struct spi_device *spi)
{
194 195
	struct s3c24xx_spi_devstate *cs = spi->controller_state;
	struct s3c24xx_spi *hw = to_hw(spi);
196 197
	int ret;

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
	/* allocate settings on the first call */
	if (!cs) {
		cs = kzalloc(sizeof(struct s3c24xx_spi_devstate), GFP_KERNEL);
		if (!cs) {
			dev_err(&spi->dev, "no memory for controller state\n");
			return -ENOMEM;
		}

		cs->spcon = SPCON_DEFAULT;
		cs->hz = -1;
		spi->controller_state = cs;
	}

	/* initialise the state from the device */
	ret = s3c24xx_spi_update_state(spi, NULL);
	if (ret)
214
		return ret;
215 216 217 218 219

	spin_lock(&hw->bitbang.lock);
	if (!hw->bitbang.busy) {
		hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
		/* need to ndelay for 0.5 clocktick ? */
220
	}
221
	spin_unlock(&hw->bitbang.lock);
222 223 224 225

	return 0;
}

226 227 228 229 230
static void s3c24xx_spi_cleanup(struct spi_device *spi)
{
	kfree(spi->controller_state);
}

231 232
static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
{
233
	return hw->tx ? hw->tx[count] : 0;
234 235
}

236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
#ifdef CONFIG_SPI_S3C24XX_FIQ
/* Support for FIQ based pseudo-DMA to improve the transfer speed.
 *
 * This code uses the assembly helper in spi_s3c24xx_spi.S which is
 * used by the FIQ core to move data between main memory and the peripheral
 * block. Since this is code running on the processor, there is no problem
 * with cache coherency of the buffers, so we can use any buffer we like.
 */

/**
 * struct spi_fiq_code - FIQ code and header
 * @length: The length of the code fragment, excluding this header.
 * @ack_offset: The offset from @data to the word to place the IRQ ACK bit at.
 * @data: The code itself to install as a FIQ handler.
 */
struct spi_fiq_code {
	u32	length;
	u32	ack_offset;
	u8	data[0];
};

extern struct spi_fiq_code s3c24xx_spi_fiq_txrx;
extern struct spi_fiq_code s3c24xx_spi_fiq_tx;
extern struct spi_fiq_code s3c24xx_spi_fiq_rx;

/**
 * ack_bit - turn IRQ into IRQ acknowledgement bit
 * @irq: The interrupt number
 *
 * Returns the bit to write to the interrupt acknowledge register.
 */
static inline u32 ack_bit(unsigned int irq)
{
	return 1 << (irq - IRQ_EINT0);
}

/**
 * s3c24xx_spi_tryfiq - attempt to claim and setup FIQ for transfer
 * @hw: The hardware state.
 *
 * Claim the FIQ handler (only one can be active at any one time) and
 * then setup the correct transfer code for this transfer.
 *
279
 * This call updates all the necessary state information if successful,
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
 * so the caller does not need to do anything more than start the transfer
 * as normal, since the IRQ will have been re-routed to the FIQ handler.
*/
void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw)
{
	struct pt_regs regs;
	enum spi_fiq_mode mode;
	struct spi_fiq_code *code;
	int ret;

	if (!hw->fiq_claimed) {
		/* try and claim fiq if we haven't got it, and if not
		 * then return and simply use another transfer method */

		ret = claim_fiq(&hw->fiq_handler);
		if (ret)
			return;
	}

	if (hw->tx && !hw->rx)
		mode = FIQ_MODE_TX;
	else if (hw->rx && !hw->tx)
		mode = FIQ_MODE_RX;
	else
		mode = FIQ_MODE_TXRX;

	regs.uregs[fiq_rspi] = (long)hw->regs;
	regs.uregs[fiq_rrx]  = (long)hw->rx;
	regs.uregs[fiq_rtx]  = (long)hw->tx + 1;
	regs.uregs[fiq_rcount] = hw->len - 1;
	regs.uregs[fiq_rirq] = (long)S3C24XX_VA_IRQ;

	set_fiq_regs(&regs);

	if (hw->fiq_mode != mode) {
		u32 *ack_ptr;

		hw->fiq_mode = mode;

		switch (mode) {
		case FIQ_MODE_TX:
			code = &s3c24xx_spi_fiq_tx;
			break;
		case FIQ_MODE_RX:
			code = &s3c24xx_spi_fiq_rx;
			break;
		case FIQ_MODE_TXRX:
			code = &s3c24xx_spi_fiq_txrx;
			break;
		default:
			code = NULL;
		}

		BUG_ON(!code);

		ack_ptr = (u32 *)&code->data[code->ack_offset];
		*ack_ptr = ack_bit(hw->irq);

		set_fiq_handler(&code->data, code->length);
	}

	s3c24xx_set_fiq(hw->irq, true);

	hw->fiq_mode = mode;
	hw->fiq_inuse = 1;
}

/**
 * s3c24xx_spi_fiqop - FIQ core code callback
 * @pw: Data registered with the handler
 * @release: Whether this is a release or a return.
 *
 * Called by the FIQ code when another module wants to use the FIQ, so
 * return whether we are currently using this or not and then update our
 * internal state.
 */
static int s3c24xx_spi_fiqop(void *pw, int release)
{
	struct s3c24xx_spi *hw = pw;
	int ret = 0;

	if (release) {
		if (hw->fiq_inuse)
			ret = -EBUSY;

		/* note, we do not need to unroute the FIQ, as the FIQ
		 * vector code de-routes it to signal the end of transfer */

		hw->fiq_mode = FIQ_MODE_NONE;
		hw->fiq_claimed = 0;
	} else {
		hw->fiq_claimed = 1;
	}

	return ret;
}

/**
 * s3c24xx_spi_initfiq - setup the information for the FIQ core
 * @hw: The hardware state.
 *
 * Setup the fiq_handler block to pass to the FIQ core.
 */
static inline void s3c24xx_spi_initfiq(struct s3c24xx_spi *hw)
{
	hw->fiq_handler.dev_id = hw;
	hw->fiq_handler.name = dev_name(hw->dev);
	hw->fiq_handler.fiq_op = s3c24xx_spi_fiqop;
}

/**
 * s3c24xx_spi_usefiq - return if we should be using FIQ.
 * @hw: The hardware state.
 *
 * Return true if the platform data specifies whether this channel is
 * allowed to use the FIQ.
 */
static inline bool s3c24xx_spi_usefiq(struct s3c24xx_spi *hw)
{
	return hw->pdata->use_fiq;
}

/**
 * s3c24xx_spi_usingfiq - return if channel is using FIQ
 * @spi: The hardware state.
 *
 * Return whether the channel is currently using the FIQ (separate from
 * whether the FIQ is claimed).
 */
static inline bool s3c24xx_spi_usingfiq(struct s3c24xx_spi *spi)
{
	return spi->fiq_inuse;
}
#else

static inline void s3c24xx_spi_initfiq(struct s3c24xx_spi *s) { }
static inline void s3c24xx_spi_tryfiq(struct s3c24xx_spi *s) { }
static inline bool s3c24xx_spi_usefiq(struct s3c24xx_spi *s) { return false; }
static inline bool s3c24xx_spi_usingfiq(struct s3c24xx_spi *s) { return false; }

#endif /* CONFIG_SPI_S3C24XX_FIQ */

422 423 424 425 426 427 428 429 430
static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
{
	struct s3c24xx_spi *hw = to_hw(spi);

	hw->tx = t->tx_buf;
	hw->rx = t->rx_buf;
	hw->len = t->len;
	hw->count = 0;

431 432
	init_completion(&hw->done);

433 434 435 436
	hw->fiq_inuse = 0;
	if (s3c24xx_spi_usefiq(hw) && t->len >= 3)
		s3c24xx_spi_tryfiq(hw);

437 438
	/* send the first byte */
	writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);
439

440 441 442 443
	wait_for_completion(&hw->done);
	return hw->count;
}

444
static irqreturn_t s3c24xx_spi_irq(int irq, void *dev)
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
{
	struct s3c24xx_spi *hw = dev;
	unsigned int spsta = readb(hw->regs + S3C2410_SPSTA);
	unsigned int count = hw->count;

	if (spsta & S3C2410_SPSTA_DCOL) {
		dev_dbg(hw->dev, "data-collision\n");
		complete(&hw->done);
		goto irq_done;
	}

	if (!(spsta & S3C2410_SPSTA_READY)) {
		dev_dbg(hw->dev, "spi not ready for tx?\n");
		complete(&hw->done);
		goto irq_done;
	}

462 463
	if (!s3c24xx_spi_usingfiq(hw)) {
		hw->count++;
464

465 466
		if (hw->rx)
			hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
467

468 469 470 471 472 473 474 475 476 477 478 479
		count++;

		if (count < hw->len)
			writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
		else
			complete(&hw->done);
	} else {
		hw->count = hw->len;
		hw->fiq_inuse = 0;

		if (hw->rx)
			hw->rx[hw->len-1] = readb(hw->regs + S3C2410_SPRDAT);
480 481

		complete(&hw->done);
482
	}
483 484 485 486 487

 irq_done:
	return IRQ_HANDLED;
}

488 489 490 491 492 493 494 495 496 497 498
static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
{
	/* for the moment, permanently enable the clock */

	clk_enable(hw->clk);

	/* program defaults into the registers */

	writeb(0xff, hw->regs + S3C2410_SPPRE);
	writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
	writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
499

500 501 502 503 504 505 506
	if (hw->pdata) {
		if (hw->set_cs == s3c24xx_spi_gpiocs)
			gpio_direction_output(hw->pdata->pin_cs, 1);

		if (hw->pdata->gpio_setup)
			hw->pdata->gpio_setup(hw->pdata, 1);
	}
507 508
}

509
static int s3c24xx_spi_probe(struct platform_device *pdev)
510
{
511
	struct s3c2410_spi_info *pdata;
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
	struct s3c24xx_spi *hw;
	struct spi_master *master;
	struct resource *res;
	int err = 0;

	master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
	if (master == NULL) {
		dev_err(&pdev->dev, "No memory for spi_master\n");
		err = -ENOMEM;
		goto err_nomem;
	}

	hw = spi_master_get_devdata(master);
	memset(hw, 0, sizeof(struct s3c24xx_spi));

	hw->master = spi_master_get(master);
528
	hw->pdata = pdata = pdev->dev.platform_data;
529 530
	hw->dev = &pdev->dev;

531
	if (pdata == NULL) {
532 533 534 535 536 537 538 539
		dev_err(&pdev->dev, "No platform data supplied\n");
		err = -ENOENT;
		goto err_no_pdata;
	}

	platform_set_drvdata(pdev, hw);
	init_completion(&hw->done);

540 541 542 543
	/* initialise fiq handler */

	s3c24xx_spi_initfiq(hw);

544 545
	/* setup the master state. */

546 547 548
	/* the spi->mode bits understood by this driver: */
	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;

549
	master->num_chipselect = hw->pdata->num_cs;
Ben Dooks's avatar
Ben Dooks committed
550
	master->bus_num = pdata->bus_num;
551

552 553 554 555 556 557
	/* setup the state for the bitbang driver */

	hw->bitbang.master         = hw->master;
	hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer;
	hw->bitbang.chipselect     = s3c24xx_spi_chipsel;
	hw->bitbang.txrx_bufs      = s3c24xx_spi_txrx;
558 559 560

	hw->master->setup  = s3c24xx_spi_setup;
	hw->master->cleanup = s3c24xx_spi_cleanup;
561 562 563 564 565 566 567 568 569 570 571 572

	dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);

	/* find and map our resources */

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
		err = -ENOENT;
		goto err_no_iores;
	}

573
	hw->ioarea = request_mem_region(res->start, resource_size(res),
574 575 576 577 578 579 580 581
					pdev->name);

	if (hw->ioarea == NULL) {
		dev_err(&pdev->dev, "Cannot reserve region\n");
		err = -ENXIO;
		goto err_no_iores;
	}

582
	hw->regs = ioremap(res->start, resource_size(res));
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
	if (hw->regs == NULL) {
		dev_err(&pdev->dev, "Cannot map IO\n");
		err = -ENXIO;
		goto err_no_iomap;
	}

	hw->irq = platform_get_irq(pdev, 0);
	if (hw->irq < 0) {
		dev_err(&pdev->dev, "No IRQ specified\n");
		err = -ENOENT;
		goto err_no_irq;
	}

	err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw);
	if (err) {
		dev_err(&pdev->dev, "Cannot claim IRQ\n");
		goto err_no_irq;
	}

	hw->clk = clk_get(&pdev->dev, "spi");
	if (IS_ERR(hw->clk)) {
		dev_err(&pdev->dev, "No clock for device\n");
		err = PTR_ERR(hw->clk);
		goto err_no_clk;
	}

	/* setup any gpio we can */

611
	if (!pdata->set_cs) {
612 613
		if (pdata->pin_cs < 0) {
			dev_err(&pdev->dev, "No chipselect pin\n");
614
			err = -EINVAL;
615 616
			goto err_register;
		}
617

618 619 620 621 622 623 624 625
		err = gpio_request(pdata->pin_cs, dev_name(&pdev->dev));
		if (err) {
			dev_err(&pdev->dev, "Failed to get gpio for cs\n");
			goto err_register;
		}

		hw->set_cs = s3c24xx_spi_gpiocs;
		gpio_direction_output(pdata->pin_cs, 1);
626
	} else
627
		hw->set_cs = pdata->set_cs;
628

629 630
	s3c24xx_spi_initialsetup(hw);

631 632 633 634 635 636 637 638 639 640 641
	/* register our spi controller */

	err = spi_bitbang_start(&hw->bitbang);
	if (err) {
		dev_err(&pdev->dev, "Failed to register SPI master\n");
		goto err_register;
	}

	return 0;

 err_register:
642 643 644
	if (hw->set_cs == s3c24xx_spi_gpiocs)
		gpio_free(pdata->pin_cs);

645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
	clk_disable(hw->clk);
	clk_put(hw->clk);

 err_no_clk:
	free_irq(hw->irq, hw);

 err_no_irq:
	iounmap(hw->regs);

 err_no_iomap:
	release_resource(hw->ioarea);
	kfree(hw->ioarea);

 err_no_iores:
 err_no_pdata:
660
	spi_master_put(hw->master);
661 662 663 664 665

 err_nomem:
	return err;
}

666
static int s3c24xx_spi_remove(struct platform_device *dev)
667 668 669 670 671
{
	struct s3c24xx_spi *hw = platform_get_drvdata(dev);

	platform_set_drvdata(dev, NULL);

672
	spi_bitbang_stop(&hw->bitbang);
673 674 675 676 677 678 679

	clk_disable(hw->clk);
	clk_put(hw->clk);

	free_irq(hw->irq, hw);
	iounmap(hw->regs);

680 681 682
	if (hw->set_cs == s3c24xx_spi_gpiocs)
		gpio_free(hw->pdata->pin_cs);

683 684 685 686 687 688 689 690 691 692
	release_resource(hw->ioarea);
	kfree(hw->ioarea);

	spi_master_put(hw->master);
	return 0;
}


#ifdef CONFIG_PM

Ben Dooks's avatar
Ben Dooks committed
693
static int s3c24xx_spi_suspend(struct device *dev)
694
{
Ben Dooks's avatar
Ben Dooks committed
695
	struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev));
696

697 698 699
	if (hw->pdata && hw->pdata->gpio_setup)
		hw->pdata->gpio_setup(hw->pdata, 0);

700 701 702 703
	clk_disable(hw->clk);
	return 0;
}

Ben Dooks's avatar
Ben Dooks committed
704
static int s3c24xx_spi_resume(struct device *dev)
705
{
Ben Dooks's avatar
Ben Dooks committed
706
	struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev));
707

708
	s3c24xx_spi_initialsetup(hw);
709 710 711
	return 0;
}

712
static const struct dev_pm_ops s3c24xx_spi_pmops = {
Ben Dooks's avatar
Ben Dooks committed
713 714 715 716 717
	.suspend	= s3c24xx_spi_suspend,
	.resume		= s3c24xx_spi_resume,
};

#define S3C24XX_SPI_PMOPS &s3c24xx_spi_pmops
718
#else
Ben Dooks's avatar
Ben Dooks committed
719 720
#define S3C24XX_SPI_PMOPS NULL
#endif /* CONFIG_PM */
721

722
MODULE_ALIAS("platform:s3c2410-spi");
Ben Dooks's avatar
Ben Dooks committed
723
static struct platform_driver s3c24xx_spi_driver = {
724
	.probe		= s3c24xx_spi_probe,
725
	.remove		= s3c24xx_spi_remove,
726 727 728
	.driver		= {
		.name	= "s3c2410-spi",
		.owner	= THIS_MODULE,
Ben Dooks's avatar
Ben Dooks committed
729
		.pm	= S3C24XX_SPI_PMOPS,
730 731
	},
};
732
module_platform_driver(s3c24xx_spi_driver);
733 734 735 736

MODULE_DESCRIPTION("S3C24XX SPI Driver");
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_LICENSE("GPL");