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.32-rc3 206 lines 5.1 kB view raw
1/* 2 * SH SCI SPI interface 3 * 4 * Copyright (c) 2008 Magnus Damm 5 * 6 * Based on S3C24XX GPIO based SPI driver, which is: 7 * Copyright (c) 2006 Ben Dooks 8 * Copyright (c) 2006 Simtec Electronics 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 * 14 */ 15 16#include <linux/kernel.h> 17#include <linux/init.h> 18#include <linux/delay.h> 19#include <linux/spinlock.h> 20#include <linux/workqueue.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/spi.h> 27#include <asm/io.h> 28 29struct sh_sci_spi { 30 struct spi_bitbang bitbang; 31 32 void __iomem *membase; 33 unsigned char val; 34 struct sh_spi_info *info; 35 struct platform_device *dev; 36}; 37 38#define SCSPTR(sp) (sp->membase + 0x1c) 39#define PIN_SCK (1 << 2) 40#define PIN_TXD (1 << 0) 41#define PIN_RXD PIN_TXD 42#define PIN_INIT ((1 << 1) | (1 << 3) | PIN_SCK | PIN_TXD) 43 44static inline void setbits(struct sh_sci_spi *sp, int bits, int on) 45{ 46 /* 47 * We are the only user of SCSPTR so no locking is required. 48 * Reading bit 2 and 0 in SCSPTR gives pin state as input. 49 * Writing the same bits sets the output value. 50 * This makes regular read-modify-write difficult so we 51 * use sp->val to keep track of the latest register value. 52 */ 53 54 if (on) 55 sp->val |= bits; 56 else 57 sp->val &= ~bits; 58 59 iowrite8(sp->val, SCSPTR(sp)); 60} 61 62static inline void setsck(struct spi_device *dev, int on) 63{ 64 setbits(spi_master_get_devdata(dev->master), PIN_SCK, on); 65} 66 67static inline void setmosi(struct spi_device *dev, int on) 68{ 69 setbits(spi_master_get_devdata(dev->master), PIN_TXD, on); 70} 71 72static inline u32 getmiso(struct spi_device *dev) 73{ 74 struct sh_sci_spi *sp = spi_master_get_devdata(dev->master); 75 76 return (ioread8(SCSPTR(sp)) & PIN_RXD) ? 1 : 0; 77} 78 79#define spidelay(x) ndelay(x) 80 81#define EXPAND_BITBANG_TXRX 82#include <linux/spi/spi_bitbang.h> 83 84static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi, 85 unsigned nsecs, u32 word, u8 bits) 86{ 87 return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); 88} 89 90static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi, 91 unsigned nsecs, u32 word, u8 bits) 92{ 93 return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); 94} 95 96static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi, 97 unsigned nsecs, u32 word, u8 bits) 98{ 99 return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); 100} 101 102static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi, 103 unsigned nsecs, u32 word, u8 bits) 104{ 105 return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); 106} 107 108static void sh_sci_spi_chipselect(struct spi_device *dev, int value) 109{ 110 struct sh_sci_spi *sp = spi_master_get_devdata(dev->master); 111 112 if (sp->info && sp->info->chip_select) 113 (sp->info->chip_select)(sp->info, dev->chip_select, value); 114} 115 116static int sh_sci_spi_probe(struct platform_device *dev) 117{ 118 struct resource *r; 119 struct spi_master *master; 120 struct sh_sci_spi *sp; 121 int ret; 122 123 master = spi_alloc_master(&dev->dev, sizeof(struct sh_sci_spi)); 124 if (master == NULL) { 125 dev_err(&dev->dev, "failed to allocate spi master\n"); 126 ret = -ENOMEM; 127 goto err0; 128 } 129 130 sp = spi_master_get_devdata(master); 131 132 platform_set_drvdata(dev, sp); 133 sp->info = dev->dev.platform_data; 134 135 /* setup spi bitbang adaptor */ 136 sp->bitbang.master = spi_master_get(master); 137 sp->bitbang.master->bus_num = sp->info->bus_num; 138 sp->bitbang.master->num_chipselect = sp->info->num_chipselect; 139 sp->bitbang.chipselect = sh_sci_spi_chipselect; 140 141 sp->bitbang.txrx_word[SPI_MODE_0] = sh_sci_spi_txrx_mode0; 142 sp->bitbang.txrx_word[SPI_MODE_1] = sh_sci_spi_txrx_mode1; 143 sp->bitbang.txrx_word[SPI_MODE_2] = sh_sci_spi_txrx_mode2; 144 sp->bitbang.txrx_word[SPI_MODE_3] = sh_sci_spi_txrx_mode3; 145 146 r = platform_get_resource(dev, IORESOURCE_MEM, 0); 147 if (r == NULL) { 148 ret = -ENOENT; 149 goto err1; 150 } 151 sp->membase = ioremap(r->start, r->end - r->start + 1); 152 if (!sp->membase) { 153 ret = -ENXIO; 154 goto err1; 155 } 156 sp->val = ioread8(SCSPTR(sp)); 157 setbits(sp, PIN_INIT, 1); 158 159 ret = spi_bitbang_start(&sp->bitbang); 160 if (!ret) 161 return 0; 162 163 setbits(sp, PIN_INIT, 0); 164 iounmap(sp->membase); 165 err1: 166 spi_master_put(sp->bitbang.master); 167 err0: 168 return ret; 169} 170 171static int sh_sci_spi_remove(struct platform_device *dev) 172{ 173 struct sh_sci_spi *sp = platform_get_drvdata(dev); 174 175 iounmap(sp->membase); 176 setbits(sp, PIN_INIT, 0); 177 spi_bitbang_stop(&sp->bitbang); 178 spi_master_put(sp->bitbang.master); 179 return 0; 180} 181 182static struct platform_driver sh_sci_spi_drv = { 183 .probe = sh_sci_spi_probe, 184 .remove = sh_sci_spi_remove, 185 .driver = { 186 .name = "spi_sh_sci", 187 .owner = THIS_MODULE, 188 }, 189}; 190 191static int __init sh_sci_spi_init(void) 192{ 193 return platform_driver_register(&sh_sci_spi_drv); 194} 195module_init(sh_sci_spi_init); 196 197static void __exit sh_sci_spi_exit(void) 198{ 199 platform_driver_unregister(&sh_sci_spi_drv); 200} 201module_exit(sh_sci_spi_exit); 202 203MODULE_DESCRIPTION("SH SCI SPI Driver"); 204MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); 205MODULE_LICENSE("GPL"); 206MODULE_ALIAS("platform:spi_sh_sci");