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 #include <linux/module.h> 26 27 #include <asm/spi.h> 28 #include <asm/io.h> 29 30 struct sh_sci_spi { 31 struct spi_bitbang bitbang; 32 33 void __iomem *membase; 34 unsigned char val; 35 struct sh_spi_info *info; 36 struct platform_device *dev; 37 }; 38 39 #define SCSPTR(sp) (sp->membase + 0x1c) 40 #define PIN_SCK (1 << 2) 41 #define PIN_TXD (1 << 0) 42 #define PIN_RXD PIN_TXD 43 #define PIN_INIT ((1 << 1) | (1 << 3) | PIN_SCK | PIN_TXD) 44 45 static inline void setbits(struct sh_sci_spi *sp, int bits, int on) 46 { 47 /* 48 * We are the only user of SCSPTR so no locking is required. 49 * Reading bit 2 and 0 in SCSPTR gives pin state as input. 50 * Writing the same bits sets the output value. 51 * This makes regular read-modify-write difficult so we 52 * use sp->val to keep track of the latest register value. 53 */ 54 55 if (on) 56 sp->val |= bits; 57 else 58 sp->val &= ~bits; 59 60 iowrite8(sp->val, SCSPTR(sp)); 61 } 62 63 static inline void setsck(struct spi_device *dev, int on) 64 { 65 setbits(spi_master_get_devdata(dev->master), PIN_SCK, on); 66 } 67 68 static inline void setmosi(struct spi_device *dev, int on) 69 { 70 setbits(spi_master_get_devdata(dev->master), PIN_TXD, on); 71 } 72 73 static inline u32 getmiso(struct spi_device *dev) 74 { 75 struct sh_sci_spi *sp = spi_master_get_devdata(dev->master); 76 77 return (ioread8(SCSPTR(sp)) & PIN_RXD) ? 1 : 0; 78 } 79 80 #define spidelay(x) ndelay(x) 81 82 #include "spi-bitbang-txrx.h" 83 84 static 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, 0, word, bits); 88 } 89 90 static 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, 0, word, bits); 94 } 95 96 static 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, 0, word, bits); 100 } 101 102 static 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, 0, word, bits); 106 } 107 108 static 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 116 static 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, resource_size(r)); 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 171 static 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 182 static 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 module_platform_driver(sh_sci_spi_drv); 191 192 MODULE_DESCRIPTION("SH SCI SPI Driver"); 193 MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); 194 MODULE_LICENSE("GPL"); 195 MODULE_ALIAS("platform:spi_sh_sci"); 196