]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/block/mg_disk.c
block: convert to pos and nr_sectors accessors
[mirror_ubuntu-zesty-kernel.git] / drivers / block / mg_disk.c
CommitLineData
3fbed4c6
K
1/*
2 * drivers/block/mg_disk.c
3 *
4 * Support for the mGine m[g]flash IO mode.
5 * Based on legacy hd.c
6 *
7 * (c) 2008 mGine Co.,LTD
8 * (c) 2008 unsik Kim <donari75@gmail.com>
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#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/fs.h>
18#include <linux/blkdev.h>
19#include <linux/hdreg.h>
8a11a789 20#include <linux/ata.h>
3fbed4c6
K
21#include <linux/interrupt.h>
22#include <linux/delay.h>
23#include <linux/platform_device.h>
24#include <linux/gpio.h>
3fbed4c6
K
25
26#define MG_RES_SEC (CONFIG_MG_DISK_RES << 1)
27
eec94620
TH
28/* name for block device */
29#define MG_DISK_NAME "mgd"
30/* name for platform device */
31#define MG_DEV_NAME "mg_disk"
32
33#define MG_DISK_MAJ 0
34#define MG_DISK_MAX_PART 16
35#define MG_SECTOR_SIZE 512
36#define MG_MAX_SECTS 256
37
38/* Register offsets */
39#define MG_BUFF_OFFSET 0x8000
40#define MG_STORAGE_BUFFER_SIZE 0x200
41#define MG_REG_OFFSET 0xC000
42#define MG_REG_FEATURE (MG_REG_OFFSET + 2) /* write case */
43#define MG_REG_ERROR (MG_REG_OFFSET + 2) /* read case */
44#define MG_REG_SECT_CNT (MG_REG_OFFSET + 4)
45#define MG_REG_SECT_NUM (MG_REG_OFFSET + 6)
46#define MG_REG_CYL_LOW (MG_REG_OFFSET + 8)
47#define MG_REG_CYL_HIGH (MG_REG_OFFSET + 0xA)
48#define MG_REG_DRV_HEAD (MG_REG_OFFSET + 0xC)
49#define MG_REG_COMMAND (MG_REG_OFFSET + 0xE) /* write case */
50#define MG_REG_STATUS (MG_REG_OFFSET + 0xE) /* read case */
51#define MG_REG_DRV_CTRL (MG_REG_OFFSET + 0x10)
52#define MG_REG_BURST_CTRL (MG_REG_OFFSET + 0x12)
53
eec94620 54/* handy status */
f68adec3
BZ
55#define MG_STAT_READY (ATA_DRDY | ATA_DSC)
56#define MG_READY_OK(s) (((s) & (MG_STAT_READY | (ATA_BUSY | ATA_DF | \
57 ATA_ERR))) == MG_STAT_READY)
eec94620
TH
58
59/* error code for others */
60#define MG_ERR_NONE 0
61#define MG_ERR_TIMEOUT 0x100
62#define MG_ERR_INIT_STAT 0x101
63#define MG_ERR_TRANSLATION 0x102
64#define MG_ERR_CTRL_RST 0x103
65#define MG_ERR_INV_STAT 0x104
66#define MG_ERR_RSTOUT 0x105
67
68#define MG_MAX_ERRORS 6 /* Max read/write errors */
69
70/* command */
71#define MG_CMD_RD 0x20
72#define MG_CMD_WR 0x30
73#define MG_CMD_SLEEP 0x99
74#define MG_CMD_WAKEUP 0xC3
75#define MG_CMD_ID 0xEC
76#define MG_CMD_WR_CONF 0x3C
77#define MG_CMD_RD_CONF 0x40
78
79/* operation mode */
80#define MG_OP_CASCADE (1 << 0)
81#define MG_OP_CASCADE_SYNC_RD (1 << 1)
82#define MG_OP_CASCADE_SYNC_WR (1 << 2)
83#define MG_OP_INTERLEAVE (1 << 3)
84
85/* synchronous */
86#define MG_BURST_LAT_4 (3 << 4)
87#define MG_BURST_LAT_5 (4 << 4)
88#define MG_BURST_LAT_6 (5 << 4)
89#define MG_BURST_LAT_7 (6 << 4)
90#define MG_BURST_LAT_8 (7 << 4)
91#define MG_BURST_LEN_4 (1 << 1)
92#define MG_BURST_LEN_8 (2 << 1)
93#define MG_BURST_LEN_16 (3 << 1)
94#define MG_BURST_LEN_32 (4 << 1)
95#define MG_BURST_LEN_CONT (0 << 1)
96
97/* timeout value (unit: ms) */
98#define MG_TMAX_CONF_TO_CMD 1
99#define MG_TMAX_WAIT_RD_DRQ 10
100#define MG_TMAX_WAIT_WR_DRQ 500
101#define MG_TMAX_RST_TO_BUSY 10
102#define MG_TMAX_HDRST_TO_RDY 500
103#define MG_TMAX_SWRST_TO_RDY 500
104#define MG_TMAX_RSTOUT 3000
105
106/* device attribution */
107/* use mflash as boot device */
108#define MG_BOOT_DEV (1 << 0)
109/* use mflash as storage device */
110#define MG_STORAGE_DEV (1 << 1)
111/* same as MG_STORAGE_DEV, but bootloader already done reset sequence */
112#define MG_STORAGE_DEV_SKIP_RST (1 << 2)
113
114#define MG_DEV_MASK (MG_BOOT_DEV | MG_STORAGE_DEV | MG_STORAGE_DEV_SKIP_RST)
115
116/* names of GPIO resource */
117#define MG_RST_PIN "mg_rst"
118/* except MG_BOOT_DEV, reset-out pin should be assigned */
119#define MG_RSTOUT_PIN "mg_rstout"
120
121/* private driver data */
122struct mg_drv_data {
123 /* disk resource */
124 u32 use_polling;
125
126 /* device attribution */
127 u32 dev_attr;
128
129 /* internally used */
130 struct mg_host *host;
131};
132
133/* main structure for mflash driver */
134struct mg_host {
135 struct device *dev;
136
137 struct request_queue *breq;
138 spinlock_t lock;
139 struct gendisk *gd;
140
141 struct timer_list timer;
142 void (*mg_do_intr) (struct mg_host *);
143
144 u16 id[ATA_ID_WORDS];
145
146 u16 cyls;
147 u16 heads;
148 u16 sectors;
149 u32 n_sectors;
150 u32 nres_sectors;
151
152 void __iomem *dev_base;
153 unsigned int irq;
154 unsigned int rst;
155 unsigned int rstout;
156
157 u32 major;
158 u32 error;
159};
160
161/*
162 * Debugging macro and defines
163 */
164#undef DO_MG_DEBUG
165#ifdef DO_MG_DEBUG
166# define MG_DBG(fmt, args...) \
167 printk(KERN_DEBUG "%s:%d "fmt, __func__, __LINE__, ##args)
168#else /* CONFIG_MG_DEBUG */
169# define MG_DBG(fmt, args...) do { } while (0)
170#endif /* CONFIG_MG_DEBUG */
171
3fbed4c6
K
172static void mg_request(struct request_queue *);
173
174static void mg_dump_status(const char *msg, unsigned int stat,
175 struct mg_host *host)
176{
177 char *name = MG_DISK_NAME;
178 struct request *req;
179
180 if (host->breq) {
181 req = elv_next_request(host->breq);
182 if (req)
183 name = req->rq_disk->disk_name;
184 }
185
186 printk(KERN_ERR "%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
f68adec3 187 if (stat & ATA_BUSY)
3fbed4c6 188 printk("Busy ");
f68adec3 189 if (stat & ATA_DRDY)
3fbed4c6 190 printk("DriveReady ");
f68adec3 191 if (stat & ATA_DF)
3fbed4c6 192 printk("WriteFault ");
f68adec3 193 if (stat & ATA_DSC)
3fbed4c6 194 printk("SeekComplete ");
f68adec3 195 if (stat & ATA_DRQ)
3fbed4c6 196 printk("DataRequest ");
f68adec3 197 if (stat & ATA_CORR)
3fbed4c6 198 printk("CorrectedError ");
f68adec3 199 if (stat & ATA_ERR)
3fbed4c6
K
200 printk("Error ");
201 printk("}\n");
f68adec3 202 if ((stat & ATA_ERR) == 0) {
3fbed4c6
K
203 host->error = 0;
204 } else {
205 host->error = inb((unsigned long)host->dev_base + MG_REG_ERROR);
206 printk(KERN_ERR "%s: %s: error=0x%02x { ", name, msg,
207 host->error & 0xff);
f68adec3 208 if (host->error & ATA_BBK)
3fbed4c6 209 printk("BadSector ");
f68adec3 210 if (host->error & ATA_UNC)
3fbed4c6 211 printk("UncorrectableError ");
f68adec3 212 if (host->error & ATA_IDNF)
3fbed4c6 213 printk("SectorIdNotFound ");
f68adec3 214 if (host->error & ATA_ABORTED)
3fbed4c6 215 printk("DriveStatusError ");
f68adec3 216 if (host->error & ATA_AMNF)
3fbed4c6
K
217 printk("AddrMarkNotFound ");
218 printk("}");
f68adec3 219 if (host->error & (ATA_BBK | ATA_UNC | ATA_IDNF | ATA_AMNF)) {
3fbed4c6
K
220 if (host->breq) {
221 req = elv_next_request(host->breq);
222 if (req)
83096ebf
TH
223 printk(", sector=%u",
224 (unsigned int)blk_rq_pos(req));
3fbed4c6
K
225 }
226
227 }
228 printk("\n");
229 }
230}
231
232static unsigned int mg_wait(struct mg_host *host, u32 expect, u32 msec)
233{
234 u8 status;
235 unsigned long expire, cur_jiffies;
236 struct mg_drv_data *prv_data = host->dev->platform_data;
237
238 host->error = MG_ERR_NONE;
239 expire = jiffies + msecs_to_jiffies(msec);
240
241 status = inb((unsigned long)host->dev_base + MG_REG_STATUS);
242
243 do {
244 cur_jiffies = jiffies;
f68adec3
BZ
245 if (status & ATA_BUSY) {
246 if (expect == ATA_BUSY)
3fbed4c6
K
247 break;
248 } else {
249 /* Check the error condition! */
f68adec3 250 if (status & ATA_ERR) {
3fbed4c6
K
251 mg_dump_status("mg_wait", status, host);
252 break;
253 }
254
255 if (expect == MG_STAT_READY)
256 if (MG_READY_OK(status))
257 break;
258
f68adec3
BZ
259 if (expect == ATA_DRQ)
260 if (status & ATA_DRQ)
3fbed4c6
K
261 break;
262 }
263 if (!msec) {
264 mg_dump_status("not ready", status, host);
265 return MG_ERR_INV_STAT;
266 }
267 if (prv_data->use_polling)
268 msleep(1);
269
270 status = inb((unsigned long)host->dev_base + MG_REG_STATUS);
271 } while (time_before(cur_jiffies, expire));
272
273 if (time_after_eq(cur_jiffies, expire) && msec)
274 host->error = MG_ERR_TIMEOUT;
275
276 return host->error;
277}
278
279static unsigned int mg_wait_rstout(u32 rstout, u32 msec)
280{
281 unsigned long expire;
282
283 expire = jiffies + msecs_to_jiffies(msec);
284 while (time_before(jiffies, expire)) {
285 if (gpio_get_value(rstout) == 1)
286 return MG_ERR_NONE;
287 msleep(10);
288 }
289
290 return MG_ERR_RSTOUT;
291}
292
293static void mg_unexpected_intr(struct mg_host *host)
294{
295 u32 status = inb((unsigned long)host->dev_base + MG_REG_STATUS);
296
297 mg_dump_status("mg_unexpected_intr", status, host);
298}
299
300static irqreturn_t mg_irq(int irq, void *dev_id)
301{
302 struct mg_host *host = dev_id;
303 void (*handler)(struct mg_host *) = host->mg_do_intr;
304
ac2ff946
TH
305 spin_lock(&host->lock);
306
307 host->mg_do_intr = NULL;
3fbed4c6
K
308 del_timer(&host->timer);
309 if (!handler)
310 handler = mg_unexpected_intr;
311 handler(host);
ac2ff946
TH
312
313 spin_unlock(&host->lock);
314
3fbed4c6
K
315 return IRQ_HANDLED;
316}
317
8a11a789
BZ
318/* local copy of ata_id_string() */
319static void mg_id_string(const u16 *id, unsigned char *s,
320 unsigned int ofs, unsigned int len)
321{
322 unsigned int c;
323
324 BUG_ON(len & 1);
325
326 while (len > 0) {
327 c = id[ofs] >> 8;
328 *s = c;
329 s++;
330
331 c = id[ofs] & 0xff;
332 *s = c;
333 s++;
334
335 ofs++;
336 len -= 2;
337 }
338}
339
340/* local copy of ata_id_c_string() */
341static void mg_id_c_string(const u16 *id, unsigned char *s,
342 unsigned int ofs, unsigned int len)
343{
344 unsigned char *p;
345
346 mg_id_string(id, s, ofs, len - 1);
347
348 p = s + strnlen(s, len - 1);
349 while (p > s && p[-1] == ' ')
350 p--;
351 *p = '\0';
352}
353
3fbed4c6
K
354static int mg_get_disk_id(struct mg_host *host)
355{
356 u32 i;
357 s32 err;
358 const u16 *id = host->id;
359 struct mg_drv_data *prv_data = host->dev->platform_data;
360 char fwrev[ATA_ID_FW_REV_LEN + 1];
361 char model[ATA_ID_PROD_LEN + 1];
362 char serial[ATA_ID_SERNO_LEN + 1];
363
364 if (!prv_data->use_polling)
f68adec3 365 outb(ATA_NIEN, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
3fbed4c6
K
366
367 outb(MG_CMD_ID, (unsigned long)host->dev_base + MG_REG_COMMAND);
f68adec3 368 err = mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_RD_DRQ);
3fbed4c6
K
369 if (err)
370 return err;
371
372 for (i = 0; i < (MG_SECTOR_SIZE >> 1); i++)
373 host->id[i] = le16_to_cpu(inw((unsigned long)host->dev_base +
374 MG_BUFF_OFFSET + i * 2));
375
376 outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base + MG_REG_COMMAND);
377 err = mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD);
378 if (err)
379 return err;
380
381 if ((id[ATA_ID_FIELD_VALID] & 1) == 0)
382 return MG_ERR_TRANSLATION;
383
384 host->n_sectors = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
385 host->cyls = id[ATA_ID_CYLS];
386 host->heads = id[ATA_ID_HEADS];
387 host->sectors = id[ATA_ID_SECTORS];
388
389 if (MG_RES_SEC && host->heads && host->sectors) {
390 /* modify cyls, n_sectors */
391 host->cyls = (host->n_sectors - MG_RES_SEC) /
392 host->heads / host->sectors;
393 host->nres_sectors = host->n_sectors - host->cyls *
394 host->heads * host->sectors;
395 host->n_sectors -= host->nres_sectors;
396 }
397
8a11a789
BZ
398 mg_id_c_string(id, fwrev, ATA_ID_FW_REV, sizeof(fwrev));
399 mg_id_c_string(id, model, ATA_ID_PROD, sizeof(model));
400 mg_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
3fbed4c6
K
401 printk(KERN_INFO "mg_disk: model: %s\n", model);
402 printk(KERN_INFO "mg_disk: firm: %.8s\n", fwrev);
403 printk(KERN_INFO "mg_disk: serial: %s\n", serial);
404 printk(KERN_INFO "mg_disk: %d + reserved %d sectors\n",
405 host->n_sectors, host->nres_sectors);
406
407 if (!prv_data->use_polling)
f68adec3 408 outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
3fbed4c6
K
409
410 return err;
411}
412
413
414static int mg_disk_init(struct mg_host *host)
415{
416 struct mg_drv_data *prv_data = host->dev->platform_data;
417 s32 err;
418 u8 init_status;
419
420 /* hdd rst low */
421 gpio_set_value(host->rst, 0);
f68adec3 422 err = mg_wait(host, ATA_BUSY, MG_TMAX_RST_TO_BUSY);
3fbed4c6
K
423 if (err)
424 return err;
425
426 /* hdd rst high */
427 gpio_set_value(host->rst, 1);
428 err = mg_wait(host, MG_STAT_READY, MG_TMAX_HDRST_TO_RDY);
429 if (err)
430 return err;
431
432 /* soft reset on */
f68adec3 433 outb(ATA_SRST | (prv_data->use_polling ? ATA_NIEN : 0),
3fbed4c6 434 (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
f68adec3 435 err = mg_wait(host, ATA_BUSY, MG_TMAX_RST_TO_BUSY);
3fbed4c6
K
436 if (err)
437 return err;
438
439 /* soft reset off */
f68adec3 440 outb(prv_data->use_polling ? ATA_NIEN : 0,
3fbed4c6
K
441 (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
442 err = mg_wait(host, MG_STAT_READY, MG_TMAX_SWRST_TO_RDY);
443 if (err)
444 return err;
445
446 init_status = inb((unsigned long)host->dev_base + MG_REG_STATUS) & 0xf;
447
448 if (init_status == 0xf)
449 return MG_ERR_INIT_STAT;
450
451 return err;
452}
453
454static void mg_bad_rw_intr(struct mg_host *host)
455{
456 struct request *req = elv_next_request(host->breq);
457 if (req != NULL)
458 if (++req->errors >= MG_MAX_ERRORS ||
459 host->error == MG_ERR_TIMEOUT)
f06d9a2b 460 __blk_end_request_cur(req, -EIO);
3fbed4c6
K
461}
462
463static unsigned int mg_out(struct mg_host *host,
464 unsigned int sect_num,
465 unsigned int sect_cnt,
466 unsigned int cmd,
467 void (*intr_addr)(struct mg_host *))
468{
469 struct mg_drv_data *prv_data = host->dev->platform_data;
470
471 if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD))
472 return host->error;
473
474 if (!prv_data->use_polling) {
475 host->mg_do_intr = intr_addr;
476 mod_timer(&host->timer, jiffies + 3 * HZ);
477 }
478 if (MG_RES_SEC)
479 sect_num += MG_RES_SEC;
480 outb((u8)sect_cnt, (unsigned long)host->dev_base + MG_REG_SECT_CNT);
481 outb((u8)sect_num, (unsigned long)host->dev_base + MG_REG_SECT_NUM);
482 outb((u8)(sect_num >> 8), (unsigned long)host->dev_base +
483 MG_REG_CYL_LOW);
484 outb((u8)(sect_num >> 16), (unsigned long)host->dev_base +
485 MG_REG_CYL_HIGH);
f68adec3 486 outb((u8)((sect_num >> 24) | ATA_LBA | ATA_DEVICE_OBS),
3fbed4c6
K
487 (unsigned long)host->dev_base + MG_REG_DRV_HEAD);
488 outb(cmd, (unsigned long)host->dev_base + MG_REG_COMMAND);
489 return MG_ERR_NONE;
490}
491
492static void mg_read(struct request *req)
493{
a03bb5a3 494 u32 j;
3fbed4c6
K
495 struct mg_host *host = req->rq_disk->private_data;
496
83096ebf
TH
497 if (mg_out(host, blk_rq_pos(req), blk_rq_sectors(req),
498 MG_CMD_RD, NULL) != MG_ERR_NONE)
3fbed4c6
K
499 mg_bad_rw_intr(host);
500
501 MG_DBG("requested %d sects (from %ld), buffer=0x%p\n",
83096ebf 502 blk_rq_sectors(req), blk_rq_pos(req), req->buffer);
a03bb5a3
TH
503
504 do {
505 u16 *buff = (u16 *)req->buffer;
3fbed4c6 506
f68adec3
BZ
507 if (mg_wait(host, ATA_DRQ,
508 MG_TMAX_WAIT_RD_DRQ) != MG_ERR_NONE) {
3fbed4c6
K
509 mg_bad_rw_intr(host);
510 return;
511 }
a03bb5a3
TH
512 for (j = 0; j < MG_SECTOR_SIZE >> 1; j++)
513 *buff++ = inw((unsigned long)host->dev_base +
514 MG_BUFF_OFFSET + (j << 1));
3fbed4c6
K
515
516 outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base +
517 MG_REG_COMMAND);
a03bb5a3 518 } while (__blk_end_request(req, 0, MG_SECTOR_SIZE));
3fbed4c6
K
519}
520
521static void mg_write(struct request *req)
522{
a03bb5a3 523 u32 j;
3fbed4c6
K
524 struct mg_host *host = req->rq_disk->private_data;
525
83096ebf
TH
526 if (mg_out(host, blk_rq_pos(req), blk_rq_sectors(req),
527 MG_CMD_WR, NULL) != MG_ERR_NONE) {
3fbed4c6
K
528 mg_bad_rw_intr(host);
529 return;
530 }
531
3fbed4c6 532 MG_DBG("requested %d sects (from %ld), buffer=0x%p\n",
83096ebf 533 blk_rq_sectors(req), blk_rq_pos(req), req->buffer);
a03bb5a3
TH
534
535 do {
536 u16 *buff = (u16 *)req->buffer;
537
f68adec3 538 if (mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) {
3fbed4c6
K
539 mg_bad_rw_intr(host);
540 return;
541 }
a03bb5a3
TH
542 for (j = 0; j < MG_SECTOR_SIZE >> 1; j++)
543 outw(*buff++, (unsigned long)host->dev_base +
544 MG_BUFF_OFFSET + (j << 1));
3fbed4c6
K
545
546 outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base +
547 MG_REG_COMMAND);
a03bb5a3 548 } while (__blk_end_request(req, 0, MG_SECTOR_SIZE));
3fbed4c6
K
549}
550
551static void mg_read_intr(struct mg_host *host)
552{
553 u32 i;
a03bb5a3 554 u16 *buff;
3fbed4c6
K
555 struct request *req;
556
557 /* check status */
558 do {
559 i = inb((unsigned long)host->dev_base + MG_REG_STATUS);
f68adec3 560 if (i & ATA_BUSY)
3fbed4c6
K
561 break;
562 if (!MG_READY_OK(i))
563 break;
f68adec3 564 if (i & ATA_DRQ)
3fbed4c6
K
565 goto ok_to_read;
566 } while (0);
567 mg_dump_status("mg_read_intr", i, host);
568 mg_bad_rw_intr(host);
569 mg_request(host->breq);
570 return;
571
572ok_to_read:
573 /* get current segment of request */
574 req = elv_next_request(host->breq);
a03bb5a3 575 buff = (u16 *)req->buffer;
3fbed4c6
K
576
577 /* read 1 sector */
a03bb5a3
TH
578 for (i = 0; i < MG_SECTOR_SIZE >> 1; i++)
579 *buff++ = inw((unsigned long)host->dev_base + MG_BUFF_OFFSET +
580 (i << 1));
3fbed4c6 581
3fbed4c6 582 MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n",
83096ebf 583 blk_rq_pos(req), blk_rq_sectors(req) - 1, req->buffer);
3fbed4c6 584
3fbed4c6
K
585 /* send read confirm */
586 outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base + MG_REG_COMMAND);
587
a03bb5a3
TH
588 if (__blk_end_request(req, 0, MG_SECTOR_SIZE)) {
589 /* set handler if read remains */
590 host->mg_do_intr = mg_read_intr;
591 mod_timer(&host->timer, jiffies + 3 * HZ);
592 } else /* goto next request */
3fbed4c6
K
593 mg_request(host->breq);
594}
595
596static void mg_write_intr(struct mg_host *host)
597{
598 u32 i, j;
599 u16 *buff;
600 struct request *req;
a03bb5a3 601 bool rem;
3fbed4c6
K
602
603 /* get current segment of request */
604 req = elv_next_request(host->breq);
605
606 /* check status */
607 do {
608 i = inb((unsigned long)host->dev_base + MG_REG_STATUS);
f68adec3 609 if (i & ATA_BUSY)
3fbed4c6
K
610 break;
611 if (!MG_READY_OK(i))
612 break;
83096ebf 613 if ((blk_rq_sectors(req) <= 1) || (i & ATA_DRQ))
3fbed4c6
K
614 goto ok_to_write;
615 } while (0);
616 mg_dump_status("mg_write_intr", i, host);
617 mg_bad_rw_intr(host);
618 mg_request(host->breq);
619 return;
620
621ok_to_write:
a03bb5a3
TH
622 if ((rem = __blk_end_request(req, 0, MG_SECTOR_SIZE))) {
623 /* write 1 sector and set handler if remains */
3fbed4c6
K
624 buff = (u16 *)req->buffer;
625 for (j = 0; j < MG_STORAGE_BUFFER_SIZE >> 1; j++) {
626 outw(*buff, (unsigned long)host->dev_base +
627 MG_BUFF_OFFSET + (j << 1));
628 buff++;
629 }
630 MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n",
83096ebf 631 blk_rq_pos(req), blk_rq_sectors(req), req->buffer);
3fbed4c6
K
632 host->mg_do_intr = mg_write_intr;
633 mod_timer(&host->timer, jiffies + 3 * HZ);
634 }
635
636 /* send write confirm */
637 outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + MG_REG_COMMAND);
638
a03bb5a3 639 if (!rem)
3fbed4c6
K
640 mg_request(host->breq);
641}
642
643void mg_times_out(unsigned long data)
644{
645 struct mg_host *host = (struct mg_host *)data;
646 char *name;
647 struct request *req;
648
ac2ff946
TH
649 spin_lock_irq(&host->lock);
650
3fbed4c6
K
651 req = elv_next_request(host->breq);
652 if (!req)
ac2ff946 653 goto out_unlock;
3fbed4c6
K
654
655 host->mg_do_intr = NULL;
656
657 name = req->rq_disk->disk_name;
658 printk(KERN_DEBUG "%s: timeout\n", name);
659
660 host->error = MG_ERR_TIMEOUT;
661 mg_bad_rw_intr(host);
662
663 mg_request(host->breq);
ac2ff946
TH
664out_unlock:
665 spin_unlock_irq(&host->lock);
3fbed4c6
K
666}
667
668static void mg_request_poll(struct request_queue *q)
669{
670 struct request *req;
671 struct mg_host *host;
672
673 while ((req = elv_next_request(q)) != NULL) {
674 host = req->rq_disk->private_data;
675 if (blk_fs_request(req)) {
676 switch (rq_data_dir(req)) {
677 case READ:
678 mg_read(req);
679 break;
680 case WRITE:
681 mg_write(req);
682 break;
3fbed4c6
K
683 }
684 }
685 }
686}
687
688static unsigned int mg_issue_req(struct request *req,
689 struct mg_host *host,
690 unsigned int sect_num,
691 unsigned int sect_cnt)
692{
693 u16 *buff;
694 u32 i;
695
696 switch (rq_data_dir(req)) {
697 case READ:
698 if (mg_out(host, sect_num, sect_cnt, MG_CMD_RD, &mg_read_intr)
699 != MG_ERR_NONE) {
700 mg_bad_rw_intr(host);
701 return host->error;
702 }
703 break;
704 case WRITE:
705 /* TODO : handler */
f68adec3 706 outb(ATA_NIEN, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
3fbed4c6
K
707 if (mg_out(host, sect_num, sect_cnt, MG_CMD_WR, &mg_write_intr)
708 != MG_ERR_NONE) {
709 mg_bad_rw_intr(host);
710 return host->error;
711 }
712 del_timer(&host->timer);
f68adec3
BZ
713 mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_WR_DRQ);
714 outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
3fbed4c6
K
715 if (host->error) {
716 mg_bad_rw_intr(host);
717 return host->error;
718 }
719 buff = (u16 *)req->buffer;
720 for (i = 0; i < MG_SECTOR_SIZE >> 1; i++) {
721 outw(*buff, (unsigned long)host->dev_base +
722 MG_BUFF_OFFSET + (i << 1));
723 buff++;
724 }
725 mod_timer(&host->timer, jiffies + 3 * HZ);
726 outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base +
727 MG_REG_COMMAND);
728 break;
3fbed4c6
K
729 }
730 return MG_ERR_NONE;
731}
732
733/* This function also called from IRQ context */
734static void mg_request(struct request_queue *q)
735{
736 struct request *req;
737 struct mg_host *host;
738 u32 sect_num, sect_cnt;
739
740 while (1) {
741 req = elv_next_request(q);
742 if (!req)
743 return;
744
745 host = req->rq_disk->private_data;
746
747 /* check unwanted request call */
748 if (host->mg_do_intr)
749 return;
750
751 del_timer(&host->timer);
752
83096ebf 753 sect_num = blk_rq_pos(req);
3fbed4c6 754 /* deal whole segments */
83096ebf 755 sect_cnt = blk_rq_sectors(req);
3fbed4c6
K
756
757 /* sanity check */
758 if (sect_num >= get_capacity(req->rq_disk) ||
759 ((sect_num + sect_cnt) >
760 get_capacity(req->rq_disk))) {
761 printk(KERN_WARNING
762 "%s: bad access: sector=%d, count=%d\n",
763 req->rq_disk->disk_name,
764 sect_num, sect_cnt);
f06d9a2b 765 __blk_end_request_cur(req, -EIO);
3fbed4c6
K
766 continue;
767 }
768
769 if (!blk_fs_request(req))
770 return;
771
772 if (!mg_issue_req(req, host, sect_num, sect_cnt))
773 return;
774 }
775}
776
777static int mg_getgeo(struct block_device *bdev, struct hd_geometry *geo)
778{
779 struct mg_host *host = bdev->bd_disk->private_data;
780
781 geo->cylinders = (unsigned short)host->cyls;
782 geo->heads = (unsigned char)host->heads;
783 geo->sectors = (unsigned char)host->sectors;
784 return 0;
785}
786
787static struct block_device_operations mg_disk_ops = {
788 .getgeo = mg_getgeo
789};
790
791static int mg_suspend(struct platform_device *plat_dev, pm_message_t state)
792{
793 struct mg_drv_data *prv_data = plat_dev->dev.platform_data;
794 struct mg_host *host = prv_data->host;
795
796 if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD))
797 return -EIO;
798
799 if (!prv_data->use_polling)
f68adec3 800 outb(ATA_NIEN, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
3fbed4c6
K
801
802 outb(MG_CMD_SLEEP, (unsigned long)host->dev_base + MG_REG_COMMAND);
803 /* wait until mflash deep sleep */
804 msleep(1);
805
806 if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD)) {
807 if (!prv_data->use_polling)
f68adec3 808 outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
3fbed4c6
K
809 return -EIO;
810 }
811
812 return 0;
813}
814
815static int mg_resume(struct platform_device *plat_dev)
816{
817 struct mg_drv_data *prv_data = plat_dev->dev.platform_data;
818 struct mg_host *host = prv_data->host;
819
820 if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD))
821 return -EIO;
822
823 outb(MG_CMD_WAKEUP, (unsigned long)host->dev_base + MG_REG_COMMAND);
824 /* wait until mflash wakeup */
825 msleep(1);
826
827 if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD))
828 return -EIO;
829
830 if (!prv_data->use_polling)
f68adec3 831 outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
3fbed4c6
K
832
833 return 0;
834}
835
836static int mg_probe(struct platform_device *plat_dev)
837{
838 struct mg_host *host;
839 struct resource *rsc;
840 struct mg_drv_data *prv_data = plat_dev->dev.platform_data;
841 int err = 0;
842
843 if (!prv_data) {
844 printk(KERN_ERR "%s:%d fail (no driver_data)\n",
845 __func__, __LINE__);
846 err = -EINVAL;
847 goto probe_err;
848 }
849
850 /* alloc mg_host */
851 host = kzalloc(sizeof(struct mg_host), GFP_KERNEL);
852 if (!host) {
853 printk(KERN_ERR "%s:%d fail (no memory for mg_host)\n",
854 __func__, __LINE__);
855 err = -ENOMEM;
856 goto probe_err;
857 }
858 host->major = MG_DISK_MAJ;
859
860 /* link each other */
861 prv_data->host = host;
862 host->dev = &plat_dev->dev;
863
864 /* io remap */
865 rsc = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
866 if (!rsc) {
867 printk(KERN_ERR "%s:%d platform_get_resource fail\n",
868 __func__, __LINE__);
869 err = -EINVAL;
870 goto probe_err_2;
871 }
872 host->dev_base = ioremap(rsc->start , rsc->end + 1);
873 if (!host->dev_base) {
874 printk(KERN_ERR "%s:%d ioremap fail\n",
875 __func__, __LINE__);
876 err = -EIO;
877 goto probe_err_2;
878 }
879 MG_DBG("dev_base = 0x%x\n", (u32)host->dev_base);
880
881 /* get reset pin */
882 rsc = platform_get_resource_byname(plat_dev, IORESOURCE_IO,
883 MG_RST_PIN);
884 if (!rsc) {
885 printk(KERN_ERR "%s:%d get reset pin fail\n",
886 __func__, __LINE__);
887 err = -EIO;
888 goto probe_err_3;
889 }
890 host->rst = rsc->start;
891
892 /* init rst pin */
893 err = gpio_request(host->rst, MG_RST_PIN);
894 if (err)
895 goto probe_err_3;
896 gpio_direction_output(host->rst, 1);
897
898 /* reset out pin */
899 if (!(prv_data->dev_attr & MG_DEV_MASK))
900 goto probe_err_3a;
901
902 if (prv_data->dev_attr != MG_BOOT_DEV) {
903 rsc = platform_get_resource_byname(plat_dev, IORESOURCE_IO,
904 MG_RSTOUT_PIN);
905 if (!rsc) {
906 printk(KERN_ERR "%s:%d get reset-out pin fail\n",
907 __func__, __LINE__);
908 err = -EIO;
909 goto probe_err_3a;
910 }
911 host->rstout = rsc->start;
912 err = gpio_request(host->rstout, MG_RSTOUT_PIN);
913 if (err)
914 goto probe_err_3a;
915 gpio_direction_input(host->rstout);
916 }
917
918 /* disk reset */
919 if (prv_data->dev_attr == MG_STORAGE_DEV) {
920 /* If POR seq. not yet finised, wait */
921 err = mg_wait_rstout(host->rstout, MG_TMAX_RSTOUT);
922 if (err)
923 goto probe_err_3b;
924 err = mg_disk_init(host);
925 if (err) {
926 printk(KERN_ERR "%s:%d fail (err code : %d)\n",
927 __func__, __LINE__, err);
928 err = -EIO;
929 goto probe_err_3b;
930 }
931 }
932
933 /* get irq resource */
934 if (!prv_data->use_polling) {
935 host->irq = platform_get_irq(plat_dev, 0);
936 if (host->irq == -ENXIO) {
937 err = host->irq;
938 goto probe_err_3b;
939 }
940 err = request_irq(host->irq, mg_irq,
941 IRQF_DISABLED | IRQF_TRIGGER_RISING,
942 MG_DEV_NAME, host);
943 if (err) {
944 printk(KERN_ERR "%s:%d fail (request_irq err=%d)\n",
945 __func__, __LINE__, err);
946 goto probe_err_3b;
947 }
948
949 }
950
951 /* get disk id */
952 err = mg_get_disk_id(host);
953 if (err) {
954 printk(KERN_ERR "%s:%d fail (err code : %d)\n",
955 __func__, __LINE__, err);
956 err = -EIO;
957 goto probe_err_4;
958 }
959
960 err = register_blkdev(host->major, MG_DISK_NAME);
961 if (err < 0) {
962 printk(KERN_ERR "%s:%d register_blkdev fail (err code : %d)\n",
963 __func__, __LINE__, err);
964 goto probe_err_4;
965 }
966 if (!host->major)
967 host->major = err;
968
969 spin_lock_init(&host->lock);
970
971 if (prv_data->use_polling)
972 host->breq = blk_init_queue(mg_request_poll, &host->lock);
973 else
974 host->breq = blk_init_queue(mg_request, &host->lock);
975
976 if (!host->breq) {
977 err = -ENOMEM;
978 printk(KERN_ERR "%s:%d (blk_init_queue) fail\n",
979 __func__, __LINE__);
980 goto probe_err_5;
981 }
982
983 /* mflash is random device, thanx for the noop */
984 elevator_exit(host->breq->elevator);
985 err = elevator_init(host->breq, "noop");
986 if (err) {
987 printk(KERN_ERR "%s:%d (elevator_init) fail\n",
988 __func__, __LINE__);
989 goto probe_err_6;
990 }
991 blk_queue_max_sectors(host->breq, MG_MAX_SECTS);
992 blk_queue_hardsect_size(host->breq, MG_SECTOR_SIZE);
993
994 init_timer(&host->timer);
995 host->timer.function = mg_times_out;
996 host->timer.data = (unsigned long)host;
997
998 host->gd = alloc_disk(MG_DISK_MAX_PART);
999 if (!host->gd) {
1000 printk(KERN_ERR "%s:%d (alloc_disk) fail\n",
1001 __func__, __LINE__);
1002 err = -ENOMEM;
1003 goto probe_err_7;
1004 }
1005 host->gd->major = host->major;
1006 host->gd->first_minor = 0;
1007 host->gd->fops = &mg_disk_ops;
1008 host->gd->queue = host->breq;
1009 host->gd->private_data = host;
1010 sprintf(host->gd->disk_name, MG_DISK_NAME"a");
1011
1012 set_capacity(host->gd, host->n_sectors);
1013
1014 add_disk(host->gd);
1015
1016 return err;
1017
1018probe_err_7:
1019 del_timer_sync(&host->timer);
1020probe_err_6:
1021 blk_cleanup_queue(host->breq);
1022probe_err_5:
1023 unregister_blkdev(MG_DISK_MAJ, MG_DISK_NAME);
1024probe_err_4:
1025 if (!prv_data->use_polling)
1026 free_irq(host->irq, host);
1027probe_err_3b:
1028 gpio_free(host->rstout);
1029probe_err_3a:
1030 gpio_free(host->rst);
1031probe_err_3:
1032 iounmap(host->dev_base);
1033probe_err_2:
1034 kfree(host);
1035probe_err:
1036 return err;
1037}
1038
1039static int mg_remove(struct platform_device *plat_dev)
1040{
1041 struct mg_drv_data *prv_data = plat_dev->dev.platform_data;
1042 struct mg_host *host = prv_data->host;
1043 int err = 0;
1044
1045 /* delete timer */
1046 del_timer_sync(&host->timer);
1047
1048 /* remove disk */
1049 if (host->gd) {
1050 del_gendisk(host->gd);
1051 put_disk(host->gd);
1052 }
1053 /* remove queue */
1054 if (host->breq)
1055 blk_cleanup_queue(host->breq);
1056
1057 /* unregister blk device */
1058 unregister_blkdev(host->major, MG_DISK_NAME);
1059
1060 /* free irq */
1061 if (!prv_data->use_polling)
1062 free_irq(host->irq, host);
1063
1064 /* free reset-out pin */
1065 if (prv_data->dev_attr != MG_BOOT_DEV)
1066 gpio_free(host->rstout);
1067
1068 /* free rst pin */
1069 if (host->rst)
1070 gpio_free(host->rst);
1071
1072 /* unmap io */
1073 if (host->dev_base)
1074 iounmap(host->dev_base);
1075
1076 /* free mg_host */
1077 kfree(host);
1078
1079 return err;
1080}
1081
1082static struct platform_driver mg_disk_driver = {
1083 .probe = mg_probe,
1084 .remove = mg_remove,
1085 .suspend = mg_suspend,
1086 .resume = mg_resume,
1087 .driver = {
1088 .name = MG_DEV_NAME,
1089 .owner = THIS_MODULE,
1090 }
1091};
1092
1093/****************************************************************************
1094 *
1095 * Module stuff
1096 *
1097 ****************************************************************************/
1098
1099static int __init mg_init(void)
1100{
1101 printk(KERN_INFO "mGine mflash driver, (c) 2008 mGine Co.\n");
1102 return platform_driver_register(&mg_disk_driver);
1103}
1104
1105static void __exit mg_exit(void)
1106{
1107 printk(KERN_INFO "mflash driver : bye bye\n");
1108 platform_driver_unregister(&mg_disk_driver);
1109}
1110
1111module_init(mg_init);
1112module_exit(mg_exit);
1113
1114MODULE_LICENSE("GPL");
1115MODULE_AUTHOR("unsik Kim <donari75@gmail.com>");
1116MODULE_DESCRIPTION("mGine m[g]flash device driver");