Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.23-rc2 456 lines 9.9 kB view raw
1/* linux/drivers/spi/spi_s3c24xx.c 2 * 3 * Copyright (c) 2006 Ben Dooks 4 * Copyright (c) 2006 Simtec Electronics 5 * Ben Dooks <ben@simtec.co.uk> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11*/ 12 13#include <linux/init.h> 14#include <linux/spinlock.h> 15#include <linux/workqueue.h> 16#include <linux/interrupt.h> 17#include <linux/delay.h> 18#include <linux/errno.h> 19#include <linux/err.h> 20#include <linux/clk.h> 21#include <linux/platform_device.h> 22 23#include <linux/spi/spi.h> 24#include <linux/spi/spi_bitbang.h> 25 26#include <asm/io.h> 27#include <asm/dma.h> 28#include <asm/hardware.h> 29 30#include <asm/arch/regs-gpio.h> 31#include <asm/plat-s3c24xx/regs-spi.h> 32#include <asm/arch/spi.h> 33 34struct s3c24xx_spi { 35 /* bitbang has to be first */ 36 struct spi_bitbang bitbang; 37 struct completion done; 38 39 void __iomem *regs; 40 int irq; 41 int len; 42 int count; 43 44 void (*set_cs)(struct s3c2410_spi_info *spi, 45 int cs, int pol); 46 47 /* data buffers */ 48 const unsigned char *tx; 49 unsigned char *rx; 50 51 struct clk *clk; 52 struct resource *ioarea; 53 struct spi_master *master; 54 struct spi_device *curdev; 55 struct device *dev; 56 struct s3c2410_spi_info *pdata; 57}; 58 59#define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT) 60#define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP) 61 62static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev) 63{ 64 return spi_master_get_devdata(sdev->master); 65} 66 67static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol) 68{ 69 s3c2410_gpio_setpin(spi->pin_cs, pol); 70} 71 72static void s3c24xx_spi_chipsel(struct spi_device *spi, int value) 73{ 74 struct s3c24xx_spi *hw = to_hw(spi); 75 unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0; 76 unsigned int spcon; 77 78 switch (value) { 79 case BITBANG_CS_INACTIVE: 80 hw->set_cs(hw->pdata, spi->chip_select, cspol^1); 81 break; 82 83 case BITBANG_CS_ACTIVE: 84 spcon = readb(hw->regs + S3C2410_SPCON); 85 86 if (spi->mode & SPI_CPHA) 87 spcon |= S3C2410_SPCON_CPHA_FMTB; 88 else 89 spcon &= ~S3C2410_SPCON_CPHA_FMTB; 90 91 if (spi->mode & SPI_CPOL) 92 spcon |= S3C2410_SPCON_CPOL_HIGH; 93 else 94 spcon &= ~S3C2410_SPCON_CPOL_HIGH; 95 96 spcon |= S3C2410_SPCON_ENSCK; 97 98 /* write new configration */ 99 100 writeb(spcon, hw->regs + S3C2410_SPCON); 101 hw->set_cs(hw->pdata, spi->chip_select, cspol); 102 103 break; 104 } 105} 106 107static int s3c24xx_spi_setupxfer(struct spi_device *spi, 108 struct spi_transfer *t) 109{ 110 struct s3c24xx_spi *hw = to_hw(spi); 111 unsigned int bpw; 112 unsigned int hz; 113 unsigned int div; 114 115 bpw = t ? t->bits_per_word : spi->bits_per_word; 116 hz = t ? t->speed_hz : spi->max_speed_hz; 117 118 if (bpw != 8) { 119 dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw); 120 return -EINVAL; 121 } 122 123 div = clk_get_rate(hw->clk) / hz; 124 125 /* is clk = pclk / (2 * (pre+1)), or is it 126 * clk = (pclk * 2) / ( pre + 1) */ 127 128 div = (div / 2) - 1; 129 130 if (div < 0) 131 div = 1; 132 133 if (div > 255) 134 div = 255; 135 136 dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", div, hz); 137 writeb(div, hw->regs + S3C2410_SPPRE); 138 139 spin_lock(&hw->bitbang.lock); 140 if (!hw->bitbang.busy) { 141 hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); 142 /* need to ndelay for 0.5 clocktick ? */ 143 } 144 spin_unlock(&hw->bitbang.lock); 145 146 return 0; 147} 148 149/* the spi->mode bits understood by this driver: */ 150#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) 151 152static int s3c24xx_spi_setup(struct spi_device *spi) 153{ 154 int ret; 155 156 if (!spi->bits_per_word) 157 spi->bits_per_word = 8; 158 159 if (spi->mode & ~MODEBITS) { 160 dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", 161 spi->mode & ~MODEBITS); 162 return -EINVAL; 163 } 164 165 ret = s3c24xx_spi_setupxfer(spi, NULL); 166 if (ret < 0) { 167 dev_err(&spi->dev, "setupxfer returned %d\n", ret); 168 return ret; 169 } 170 171 dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", 172 __FUNCTION__, spi->mode, spi->bits_per_word, 173 spi->max_speed_hz); 174 175 return 0; 176} 177 178static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count) 179{ 180 return hw->tx ? hw->tx[count] : 0; 181} 182 183static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t) 184{ 185 struct s3c24xx_spi *hw = to_hw(spi); 186 187 dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", 188 t->tx_buf, t->rx_buf, t->len); 189 190 hw->tx = t->tx_buf; 191 hw->rx = t->rx_buf; 192 hw->len = t->len; 193 hw->count = 0; 194 195 /* send the first byte */ 196 writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT); 197 wait_for_completion(&hw->done); 198 199 return hw->count; 200} 201 202static irqreturn_t s3c24xx_spi_irq(int irq, void *dev) 203{ 204 struct s3c24xx_spi *hw = dev; 205 unsigned int spsta = readb(hw->regs + S3C2410_SPSTA); 206 unsigned int count = hw->count; 207 208 if (spsta & S3C2410_SPSTA_DCOL) { 209 dev_dbg(hw->dev, "data-collision\n"); 210 complete(&hw->done); 211 goto irq_done; 212 } 213 214 if (!(spsta & S3C2410_SPSTA_READY)) { 215 dev_dbg(hw->dev, "spi not ready for tx?\n"); 216 complete(&hw->done); 217 goto irq_done; 218 } 219 220 hw->count++; 221 222 if (hw->rx) 223 hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT); 224 225 count++; 226 227 if (count < hw->len) 228 writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT); 229 else 230 complete(&hw->done); 231 232 irq_done: 233 return IRQ_HANDLED; 234} 235 236static int s3c24xx_spi_probe(struct platform_device *pdev) 237{ 238 struct s3c24xx_spi *hw; 239 struct spi_master *master; 240 struct spi_board_info *bi; 241 struct resource *res; 242 int err = 0; 243 int i; 244 245 master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi)); 246 if (master == NULL) { 247 dev_err(&pdev->dev, "No memory for spi_master\n"); 248 err = -ENOMEM; 249 goto err_nomem; 250 } 251 252 hw = spi_master_get_devdata(master); 253 memset(hw, 0, sizeof(struct s3c24xx_spi)); 254 255 hw->master = spi_master_get(master); 256 hw->pdata = pdev->dev.platform_data; 257 hw->dev = &pdev->dev; 258 259 if (hw->pdata == NULL) { 260 dev_err(&pdev->dev, "No platform data supplied\n"); 261 err = -ENOENT; 262 goto err_no_pdata; 263 } 264 265 platform_set_drvdata(pdev, hw); 266 init_completion(&hw->done); 267 268 /* setup the state for the bitbang driver */ 269 270 hw->bitbang.master = hw->master; 271 hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer; 272 hw->bitbang.chipselect = s3c24xx_spi_chipsel; 273 hw->bitbang.txrx_bufs = s3c24xx_spi_txrx; 274 hw->bitbang.master->setup = s3c24xx_spi_setup; 275 276 dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang); 277 278 /* find and map our resources */ 279 280 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 281 if (res == NULL) { 282 dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); 283 err = -ENOENT; 284 goto err_no_iores; 285 } 286 287 hw->ioarea = request_mem_region(res->start, (res->end - res->start)+1, 288 pdev->name); 289 290 if (hw->ioarea == NULL) { 291 dev_err(&pdev->dev, "Cannot reserve region\n"); 292 err = -ENXIO; 293 goto err_no_iores; 294 } 295 296 hw->regs = ioremap(res->start, (res->end - res->start)+1); 297 if (hw->regs == NULL) { 298 dev_err(&pdev->dev, "Cannot map IO\n"); 299 err = -ENXIO; 300 goto err_no_iomap; 301 } 302 303 hw->irq = platform_get_irq(pdev, 0); 304 if (hw->irq < 0) { 305 dev_err(&pdev->dev, "No IRQ specified\n"); 306 err = -ENOENT; 307 goto err_no_irq; 308 } 309 310 err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw); 311 if (err) { 312 dev_err(&pdev->dev, "Cannot claim IRQ\n"); 313 goto err_no_irq; 314 } 315 316 hw->clk = clk_get(&pdev->dev, "spi"); 317 if (IS_ERR(hw->clk)) { 318 dev_err(&pdev->dev, "No clock for device\n"); 319 err = PTR_ERR(hw->clk); 320 goto err_no_clk; 321 } 322 323 /* for the moment, permanently enable the clock */ 324 325 clk_enable(hw->clk); 326 327 /* program defaults into the registers */ 328 329 writeb(0xff, hw->regs + S3C2410_SPPRE); 330 writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN); 331 writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON); 332 333 /* setup any gpio we can */ 334 335 if (!hw->pdata->set_cs) { 336 hw->set_cs = s3c24xx_spi_gpiocs; 337 338 s3c2410_gpio_setpin(hw->pdata->pin_cs, 1); 339 s3c2410_gpio_cfgpin(hw->pdata->pin_cs, S3C2410_GPIO_OUTPUT); 340 } else 341 hw->set_cs = hw->pdata->set_cs; 342 343 /* register our spi controller */ 344 345 err = spi_bitbang_start(&hw->bitbang); 346 if (err) { 347 dev_err(&pdev->dev, "Failed to register SPI master\n"); 348 goto err_register; 349 } 350 351 /* register all the devices associated */ 352 353 bi = &hw->pdata->board_info[0]; 354 for (i = 0; i < hw->pdata->board_size; i++, bi++) { 355 dev_info(hw->dev, "registering %s\n", bi->modalias); 356 357 bi->controller_data = hw; 358 spi_new_device(master, bi); 359 } 360 361 return 0; 362 363 err_register: 364 clk_disable(hw->clk); 365 clk_put(hw->clk); 366 367 err_no_clk: 368 free_irq(hw->irq, hw); 369 370 err_no_irq: 371 iounmap(hw->regs); 372 373 err_no_iomap: 374 release_resource(hw->ioarea); 375 kfree(hw->ioarea); 376 377 err_no_iores: 378 err_no_pdata: 379 spi_master_put(hw->master);; 380 381 err_nomem: 382 return err; 383} 384 385static int s3c24xx_spi_remove(struct platform_device *dev) 386{ 387 struct s3c24xx_spi *hw = platform_get_drvdata(dev); 388 389 platform_set_drvdata(dev, NULL); 390 391 spi_unregister_master(hw->master); 392 393 clk_disable(hw->clk); 394 clk_put(hw->clk); 395 396 free_irq(hw->irq, hw); 397 iounmap(hw->regs); 398 399 release_resource(hw->ioarea); 400 kfree(hw->ioarea); 401 402 spi_master_put(hw->master); 403 return 0; 404} 405 406 407#ifdef CONFIG_PM 408 409static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg) 410{ 411 struct s3c24xx_spi *hw = platform_get_drvdata(pdev); 412 413 clk_disable(hw->clk); 414 return 0; 415} 416 417static int s3c24xx_spi_resume(struct platform_device *pdev) 418{ 419 struct s3c24xx_spi *hw = platform_get_drvdata(pdev); 420 421 clk_enable(hw->clk); 422 return 0; 423} 424 425#else 426#define s3c24xx_spi_suspend NULL 427#define s3c24xx_spi_resume NULL 428#endif 429 430static struct platform_driver s3c24xx_spidrv = { 431 .probe = s3c24xx_spi_probe, 432 .remove = s3c24xx_spi_remove, 433 .suspend = s3c24xx_spi_suspend, 434 .resume = s3c24xx_spi_resume, 435 .driver = { 436 .name = "s3c2410-spi", 437 .owner = THIS_MODULE, 438 }, 439}; 440 441static int __init s3c24xx_spi_init(void) 442{ 443 return platform_driver_register(&s3c24xx_spidrv); 444} 445 446static void __exit s3c24xx_spi_exit(void) 447{ 448 platform_driver_unregister(&s3c24xx_spidrv); 449} 450 451module_init(s3c24xx_spi_init); 452module_exit(s3c24xx_spi_exit); 453 454MODULE_DESCRIPTION("S3C24XX SPI Driver"); 455MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 456MODULE_LICENSE("GPL");