0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009
0010 #include <linux/init.h>
0011 #include <linux/module.h>
0012 #include <linux/kernel.h>
0013 #include <linux/delay.h>
0014 #include <linux/device.h>
0015 #include <linux/parport.h>
0016 #include <linux/sysfs.h>
0017 #include <linux/workqueue.h>
0018
0019 #include <linux/spi/spi.h>
0020 #include <linux/spi/spi_bitbang.h>
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 #define DRVNAME "spi-lm70llp"
0062
0063 #define lm70_INIT 0xBE
0064 #define SIO 0x10
0065 #define nCS 0x20
0066 #define SCLK 0x40
0067
0068
0069
0070 struct spi_lm70llp {
0071 struct spi_bitbang bitbang;
0072 struct parport *port;
0073 struct pardevice *pd;
0074 struct spi_device *spidev_lm70;
0075 struct spi_board_info info;
0076
0077 };
0078
0079
0080 static struct spi_lm70llp *lm70llp;
0081
0082
0083
0084 static inline struct spi_lm70llp *spidev_to_pp(struct spi_device *spi)
0085 {
0086 return spi->controller_data;
0087 }
0088
0089
0090
0091
0092
0093
0094
0095
0096 static inline void deassertCS(struct spi_lm70llp *pp)
0097 {
0098 u8 data = parport_read_data(pp->port);
0099
0100 data &= ~0x80;
0101 parport_write_data(pp->port, data | nCS);
0102 }
0103
0104 static inline void assertCS(struct spi_lm70llp *pp)
0105 {
0106 u8 data = parport_read_data(pp->port);
0107
0108 data |= 0x80;
0109 parport_write_data(pp->port, data & ~nCS);
0110 }
0111
0112 static inline void clkHigh(struct spi_lm70llp *pp)
0113 {
0114 u8 data = parport_read_data(pp->port);
0115
0116 parport_write_data(pp->port, data | SCLK);
0117 }
0118
0119 static inline void clkLow(struct spi_lm70llp *pp)
0120 {
0121 u8 data = parport_read_data(pp->port);
0122
0123 parport_write_data(pp->port, data & ~SCLK);
0124 }
0125
0126
0127
0128 static inline void spidelay(unsigned d)
0129 {
0130 udelay(d);
0131 }
0132
0133 static inline void setsck(struct spi_device *s, int is_on)
0134 {
0135 struct spi_lm70llp *pp = spidev_to_pp(s);
0136
0137 if (is_on)
0138 clkHigh(pp);
0139 else
0140 clkLow(pp);
0141 }
0142
0143 static inline void setmosi(struct spi_device *s, int is_on)
0144 {
0145
0146
0147
0148
0149 }
0150
0151
0152
0153
0154
0155
0156
0157
0158 static inline int getmiso(struct spi_device *s)
0159 {
0160 struct spi_lm70llp *pp = spidev_to_pp(s);
0161
0162 return ((SIO == (parport_read_status(pp->port) & SIO)) ? 0 : 1);
0163 }
0164
0165
0166
0167 #include "spi-bitbang-txrx.h"
0168
0169 static void lm70_chipselect(struct spi_device *spi, int value)
0170 {
0171 struct spi_lm70llp *pp = spidev_to_pp(spi);
0172
0173 if (value)
0174 assertCS(pp);
0175 else
0176 deassertCS(pp);
0177 }
0178
0179
0180
0181
0182 static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits,
0183 unsigned flags)
0184 {
0185 return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
0186 }
0187
0188 static void spi_lm70llp_attach(struct parport *p)
0189 {
0190 struct pardevice *pd;
0191 struct spi_lm70llp *pp;
0192 struct spi_master *master;
0193 int status;
0194 struct pardev_cb lm70llp_cb;
0195
0196 if (lm70llp) {
0197 pr_warn("spi_lm70llp instance already loaded. Aborting.\n");
0198 return;
0199 }
0200
0201
0202
0203
0204
0205 master = spi_alloc_master(p->physport->dev, sizeof(*pp));
0206 if (!master) {
0207 status = -ENOMEM;
0208 goto out_fail;
0209 }
0210 pp = spi_master_get_devdata(master);
0211
0212
0213
0214
0215 pp->bitbang.master = master;
0216 pp->bitbang.chipselect = lm70_chipselect;
0217 pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx;
0218 pp->bitbang.flags = SPI_3WIRE;
0219
0220
0221
0222
0223 pp->port = p;
0224 memset(&lm70llp_cb, 0, sizeof(lm70llp_cb));
0225 lm70llp_cb.private = pp;
0226 lm70llp_cb.flags = PARPORT_FLAG_EXCL;
0227 pd = parport_register_dev_model(p, DRVNAME, &lm70llp_cb, 0);
0228
0229 if (!pd) {
0230 status = -ENOMEM;
0231 goto out_free_master;
0232 }
0233 pp->pd = pd;
0234
0235 status = parport_claim(pd);
0236 if (status < 0)
0237 goto out_parport_unreg;
0238
0239
0240
0241
0242 status = spi_bitbang_start(&pp->bitbang);
0243 if (status < 0) {
0244 dev_warn(&pd->dev, "spi_bitbang_start failed with status %d\n",
0245 status);
0246 goto out_off_and_release;
0247 }
0248
0249
0250
0251
0252
0253
0254
0255 strcpy(pp->info.modalias, "lm70");
0256 pp->info.max_speed_hz = 6 * 1000 * 1000;
0257 pp->info.chip_select = 0;
0258 pp->info.mode = SPI_3WIRE | SPI_MODE_0;
0259
0260
0261 parport_write_data(pp->port, lm70_INIT);
0262
0263
0264
0265
0266 pp->info.controller_data = pp;
0267 pp->spidev_lm70 = spi_new_device(pp->bitbang.master, &pp->info);
0268 if (pp->spidev_lm70)
0269 dev_dbg(&pp->spidev_lm70->dev, "spidev_lm70 at %s\n",
0270 dev_name(&pp->spidev_lm70->dev));
0271 else {
0272 dev_warn(&pd->dev, "spi_new_device failed\n");
0273 status = -ENODEV;
0274 goto out_bitbang_stop;
0275 }
0276 pp->spidev_lm70->bits_per_word = 8;
0277
0278 lm70llp = pp;
0279 return;
0280
0281 out_bitbang_stop:
0282 spi_bitbang_stop(&pp->bitbang);
0283 out_off_and_release:
0284
0285 parport_write_data(pp->port, 0);
0286 mdelay(10);
0287 parport_release(pp->pd);
0288 out_parport_unreg:
0289 parport_unregister_device(pd);
0290 out_free_master:
0291 spi_master_put(master);
0292 out_fail:
0293 pr_info("spi_lm70llp probe fail, status %d\n", status);
0294 }
0295
0296 static void spi_lm70llp_detach(struct parport *p)
0297 {
0298 struct spi_lm70llp *pp;
0299
0300 if (!lm70llp || lm70llp->port != p)
0301 return;
0302
0303 pp = lm70llp;
0304 spi_bitbang_stop(&pp->bitbang);
0305
0306
0307 parport_write_data(pp->port, 0);
0308
0309 parport_release(pp->pd);
0310 parport_unregister_device(pp->pd);
0311
0312 spi_master_put(pp->bitbang.master);
0313
0314 lm70llp = NULL;
0315 }
0316
0317 static struct parport_driver spi_lm70llp_drv = {
0318 .name = DRVNAME,
0319 .match_port = spi_lm70llp_attach,
0320 .detach = spi_lm70llp_detach,
0321 .devmodel = true,
0322 };
0323 module_parport_driver(spi_lm70llp_drv);
0324
0325 MODULE_AUTHOR("Kaiwan N Billimoria <kaiwan@designergraphix.com>");
0326 MODULE_DESCRIPTION(
0327 "Parport adapter for the National Semiconductor LM70 LLP eval board");
0328 MODULE_LICENSE("GPL");