101-pata-magicbox-cf-driver.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. --- a/drivers/ata/Kconfig
  2. +++ b/drivers/ata/Kconfig
  3. @@ -745,6 +745,16 @@ config PATA_IXP4XX_CF
  4. If unsure, say N.
  5. +config PATA_MAGICBOX_CF
  6. + tristate "Magicbox/OpenRB Compact Flash support"
  7. + depends on MAGICBOX || OPENRB
  8. + help
  9. + This option enables support for a Compact Flash conected on
  10. + the ppc405ep expansion bus. This driver had been written for
  11. + the Magicbox v2 and OpenRB boards.
  12. +
  13. + If unsure, say N.
  14. +
  15. config PATA_OCTEON_CF
  16. tristate "OCTEON Boot Bus Compact Flash support"
  17. depends on CPU_CAVIUM_OCTEON
  18. --- a/drivers/ata/Makefile
  19. +++ b/drivers/ata/Makefile
  20. @@ -49,6 +49,7 @@ obj-$(CONFIG_PATA_OPTI) += pata_opti.o
  21. obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o
  22. obj-$(CONFIG_PATA_MPC52xx) += pata_mpc52xx.o
  23. obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o
  24. +obj-$(CONFIG_PATA_MAGICBOX_CF) += pata_magicbox_cf.o
  25. obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o
  26. obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o
  27. obj-$(CONFIG_PATA_PALMLD) += pata_palmld.o
  28. --- /dev/null
  29. +++ b/drivers/ata/pata_magicbox_cf.c
  30. @@ -0,0 +1,404 @@
  31. +/*
  32. + * PATA/CompactFlash driver for the MagicBox v2/OpenRB boards.
  33. + *
  34. + * Copyright (C) 2009 Gabor Juhos <[email protected]>
  35. + *
  36. + * Based on the IDE driver by Wojtek Kaniewski <[email protected]>
  37. + *
  38. + * This program is free software; you can redistribute it and/or modify it
  39. + * under the terms of the GNU General Public License version 2 as published
  40. + * by the Free Software Foundation.
  41. + */
  42. +
  43. +#include <linux/kernel.h>
  44. +#include <linux/module.h>
  45. +#include <linux/types.h>
  46. +#include <linux/ioport.h>
  47. +#include <linux/libata.h>
  48. +#include <linux/irq.h>
  49. +#include <linux/of.h>
  50. +#include <linux/of_device.h>
  51. +#include <linux/of_platform.h>
  52. +#include <scsi/scsi_host.h>
  53. +
  54. +#define DRV_DESC "PATA/CompactFlash driver for Magicbox/OpenRB boards"
  55. +#define DRV_NAME "pata_magicbox_cf"
  56. +#define DRV_VERSION "0.1.0"
  57. +
  58. +#define MAGICBOX_CF_REG_CMD (2 * ATA_REG_CMD)
  59. +#define MAGICBOX_CF_REG_DATA (2 * ATA_REG_DATA)
  60. +#define MAGICBOX_CF_REG_ERR (2 * ATA_REG_ERR)
  61. +#define MAGICBOX_CF_REG_FEATURE (2 * ATA_REG_FEATURE)
  62. +#define MAGICBOX_CF_REG_NSECT (2 * ATA_REG_NSECT)
  63. +#define MAGICBOX_CF_REG_LBAL (2 * ATA_REG_LBAL)
  64. +#define MAGICBOX_CF_REG_LBAM (2 * ATA_REG_LBAM)
  65. +#define MAGICBOX_CF_REG_LBAH (2 * ATA_REG_LBAH)
  66. +#define MAGICBOX_CF_REG_DEVICE (2 * ATA_REG_DEVICE)
  67. +#define MAGICBOX_CF_REG_STATUS (2 * ATA_REG_STATUS)
  68. +#define MAGICBOX_CF_REG_ALTSTATUS (2 * 6)
  69. +#define MAGICBOX_CF_REG_CTL (2 * 6)
  70. +
  71. +#define MAGICBOX_CF_MAXPORTS 1
  72. +
  73. +struct magicbox_cf_info {
  74. + void __iomem *base;
  75. + void __iomem *ctrl;
  76. +};
  77. +
  78. +static inline u8 magicbox_cf_inb(void __iomem *port)
  79. +{
  80. + return (u8) (readw(port) >> 8) & 0xff;
  81. +}
  82. +
  83. +static inline void magicbox_cf_outb(void __iomem *port, u8 value)
  84. +{
  85. + writew(value << 8, port);
  86. +}
  87. +
  88. +static int magicbox_cf_set_mode(struct ata_link *link,
  89. + struct ata_device **error)
  90. +{
  91. + struct ata_device *dev;
  92. +
  93. + ata_for_each_dev(dev, link, ENABLED) {
  94. + ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n");
  95. + dev->pio_mode = XFER_PIO_0;
  96. + dev->xfer_mode = XFER_PIO_0;
  97. + dev->xfer_shift = ATA_SHIFT_PIO;
  98. + dev->flags |= ATA_DFLAG_PIO;
  99. + }
  100. +
  101. + return 0;
  102. +}
  103. +
  104. +static void magicbox_cf_exec_command(struct ata_port *ap,
  105. + const struct ata_taskfile *tf)
  106. +{
  107. + DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
  108. +
  109. + magicbox_cf_outb(ap->ioaddr.command_addr, tf->command);
  110. + ata_sff_pause(ap);
  111. +}
  112. +
  113. +static u8 magicbox_cf_check_status(struct ata_port *ap)
  114. +{
  115. + u8 status;
  116. +
  117. + status = magicbox_cf_inb(ap->ioaddr.status_addr);
  118. +
  119. + DPRINTK("ata%u: status 0x%X, from %p\n", ap->print_id, status,
  120. + ap->ioaddr.status_addr);
  121. +
  122. + return status;
  123. +}
  124. +
  125. +static u8 magicbox_cf_check_altstatus(struct ata_port *ap)
  126. +{
  127. + u8 altstatus;
  128. +
  129. + altstatus = magicbox_cf_inb(ap->ioaddr.altstatus_addr);
  130. +
  131. + DPRINTK("ata%u: altstatus 0x%X, from %p\n", ap->print_id,
  132. + altstatus, ap->ioaddr.altstatus_addr);
  133. +
  134. + return altstatus;
  135. +}
  136. +
  137. +static void magicbox_cf_dev_select(struct ata_port *ap, unsigned int device)
  138. +{
  139. + /* Nothing to do. We are supporting one device only. */
  140. +}
  141. +
  142. +static void magicbox_cf_tf_load(struct ata_port *ap,
  143. + const struct ata_taskfile *tf)
  144. +{
  145. + struct ata_ioports *ioaddr = &ap->ioaddr;
  146. + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
  147. +
  148. + if (tf->ctl != ap->last_ctl) {
  149. + magicbox_cf_outb(ioaddr->ctl_addr, tf->ctl);
  150. + ap->last_ctl = tf->ctl;
  151. + ata_wait_idle(ap);
  152. + }
  153. +
  154. + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
  155. + magicbox_cf_outb(ioaddr->feature_addr, tf->hob_feature);
  156. + magicbox_cf_outb(ioaddr->nsect_addr, tf->hob_nsect);
  157. + magicbox_cf_outb(ioaddr->lbal_addr, tf->hob_lbal);
  158. + magicbox_cf_outb(ioaddr->lbam_addr, tf->hob_lbam);
  159. + magicbox_cf_outb(ioaddr->lbah_addr, tf->hob_lbah);
  160. + VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
  161. + tf->hob_feature,
  162. + tf->hob_nsect,
  163. + tf->hob_lbal,
  164. + tf->hob_lbam,
  165. + tf->hob_lbah);
  166. + }
  167. +
  168. + if (is_addr) {
  169. + magicbox_cf_outb(ioaddr->feature_addr, tf->feature);
  170. + magicbox_cf_outb(ioaddr->nsect_addr, tf->nsect);
  171. + magicbox_cf_outb(ioaddr->lbal_addr, tf->lbal);
  172. + magicbox_cf_outb(ioaddr->lbam_addr, tf->lbam);
  173. + magicbox_cf_outb(ioaddr->lbah_addr, tf->lbah);
  174. + VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
  175. + tf->feature,
  176. + tf->nsect,
  177. + tf->lbal,
  178. + tf->lbam,
  179. + tf->lbah);
  180. + }
  181. +
  182. + if (tf->flags & ATA_TFLAG_DEVICE) {
  183. + magicbox_cf_outb(ioaddr->device_addr, tf->device);
  184. + VPRINTK("device 0x%X\n", tf->device);
  185. + }
  186. +
  187. + ata_wait_idle(ap);
  188. +}
  189. +
  190. +static void magicbox_cf_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
  191. +{
  192. + struct ata_ioports *ioaddr = &ap->ioaddr;
  193. +
  194. + tf->command = magicbox_cf_inb(ap->ioaddr.status_addr);
  195. + tf->feature = magicbox_cf_inb(ioaddr->error_addr);
  196. + tf->nsect = magicbox_cf_inb(ioaddr->nsect_addr);
  197. + tf->lbal = magicbox_cf_inb(ioaddr->lbal_addr);
  198. + tf->lbam = magicbox_cf_inb(ioaddr->lbam_addr);
  199. + tf->lbah = magicbox_cf_inb(ioaddr->lbah_addr);
  200. + tf->device = magicbox_cf_inb(ioaddr->device_addr);
  201. + VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
  202. + tf->feature,
  203. + tf->nsect,
  204. + tf->lbal,
  205. + tf->lbam,
  206. + tf->lbah);
  207. +
  208. + if (tf->flags & ATA_TFLAG_LBA48) {
  209. + magicbox_cf_outb(ioaddr->ctl_addr, tf->ctl | ATA_HOB);
  210. + tf->hob_feature = magicbox_cf_inb(ioaddr->error_addr);
  211. + tf->hob_nsect = magicbox_cf_inb(ioaddr->nsect_addr);
  212. + tf->hob_lbal = magicbox_cf_inb(ioaddr->lbal_addr);
  213. + tf->hob_lbam = magicbox_cf_inb(ioaddr->lbam_addr);
  214. + tf->hob_lbah = magicbox_cf_inb(ioaddr->lbah_addr);
  215. + magicbox_cf_outb(ioaddr->ctl_addr, tf->ctl);
  216. + ap->last_ctl = tf->ctl;
  217. + VPRINTK("hob: feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
  218. + tf->feature,
  219. + tf->nsect,
  220. + tf->lbal,
  221. + tf->lbam,
  222. + tf->lbah);
  223. + }
  224. +}
  225. +
  226. +static unsigned int magicbox_cf_data_xfer(struct ata_device *dev,
  227. + unsigned char *buf,
  228. + unsigned int buflen, int rw)
  229. +{
  230. + struct ata_port *ap = dev->link->ap;
  231. + unsigned int words = buflen >> 1;
  232. + unsigned int i;
  233. + u16 *buf16 = (u16 *) buf;
  234. + void __iomem *mmio = ap->ioaddr.data_addr;
  235. +
  236. + /* Transfer multiple of 2 bytes */
  237. + if (rw == READ)
  238. + for (i = 0; i < words; i++)
  239. + buf16[i] = readw(mmio);
  240. + else
  241. + for (i = 0; i < words; i++)
  242. + writew(buf16[i], mmio);
  243. +
  244. + /* Transfer trailing 1 byte, if any. */
  245. + if (unlikely(buflen & 0x01)) {
  246. + u16 align_buf[1] = { 0 };
  247. + unsigned char *trailing_buf = buf + buflen - 1;
  248. +
  249. + if (rw == READ) {
  250. + align_buf[0] = readw(mmio);
  251. + memcpy(trailing_buf, align_buf, 1);
  252. + } else {
  253. + memcpy(align_buf, trailing_buf, 1);
  254. + writew(align_buf[0], mmio);
  255. + }
  256. + words++;
  257. + }
  258. +
  259. + return words << 1;
  260. +}
  261. +
  262. +static u8 magicbox_cf_irq_on(struct ata_port *ap)
  263. +{
  264. + /* Nothing to do. */
  265. + return 0;
  266. +}
  267. +
  268. +static void magicbox_cf_irq_clear(struct ata_port *ap)
  269. +{
  270. + /* Nothing to do. */
  271. +}
  272. +
  273. +static struct ata_port_operations magicbox_cf_port_ops = {
  274. + .inherits = &ata_sff_port_ops,
  275. +
  276. + .cable_detect = ata_cable_40wire,
  277. + .set_mode = magicbox_cf_set_mode,
  278. +
  279. + .sff_exec_command = magicbox_cf_exec_command,
  280. + .sff_check_status = magicbox_cf_check_status,
  281. + .sff_check_altstatus = magicbox_cf_check_altstatus,
  282. + .sff_dev_select = magicbox_cf_dev_select,
  283. + .sff_tf_load = magicbox_cf_tf_load,
  284. + .sff_tf_read = magicbox_cf_tf_read,
  285. + .sff_data_xfer = magicbox_cf_data_xfer,
  286. +
  287. + .sff_irq_on = magicbox_cf_irq_on,
  288. + .sff_irq_clear = magicbox_cf_irq_clear,
  289. +
  290. + .port_start = ATA_OP_NULL,
  291. +};
  292. +
  293. +static struct scsi_host_template magicbox_cf_sht = {
  294. + ATA_PIO_SHT(DRV_NAME),
  295. +};
  296. +
  297. +static inline void magicbox_cf_setup_port(struct ata_host *host)
  298. +{
  299. + struct magicbox_cf_info *info = host->private_data;
  300. + struct ata_port *ap;
  301. +
  302. + ap = host->ports[0];
  303. +
  304. + ap->ops = &magicbox_cf_port_ops;
  305. + ap->pio_mask = ATA_PIO4;
  306. + ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI;
  307. +
  308. + ap->ioaddr.cmd_addr = info->base + MAGICBOX_CF_REG_CMD;
  309. + ap->ioaddr.data_addr = info->base + MAGICBOX_CF_REG_DATA;
  310. + ap->ioaddr.error_addr = info->base + MAGICBOX_CF_REG_ERR;
  311. + ap->ioaddr.feature_addr = info->base + MAGICBOX_CF_REG_FEATURE;
  312. + ap->ioaddr.nsect_addr = info->base + MAGICBOX_CF_REG_NSECT;
  313. + ap->ioaddr.lbal_addr = info->base + MAGICBOX_CF_REG_LBAL;
  314. + ap->ioaddr.lbam_addr = info->base + MAGICBOX_CF_REG_LBAM;
  315. + ap->ioaddr.lbah_addr = info->base + MAGICBOX_CF_REG_LBAH;
  316. + ap->ioaddr.device_addr = info->base + MAGICBOX_CF_REG_DEVICE;
  317. + ap->ioaddr.status_addr = info->base + MAGICBOX_CF_REG_STATUS;
  318. + ap->ioaddr.command_addr = info->base + MAGICBOX_CF_REG_CMD;
  319. +
  320. + ap->ioaddr.altstatus_addr = info->ctrl + MAGICBOX_CF_REG_ALTSTATUS;
  321. + ap->ioaddr.ctl_addr = info->ctrl + MAGICBOX_CF_REG_CTL;
  322. +
  323. + ata_port_desc(ap, "cmd 0x%p ctl 0x%p", ap->ioaddr.cmd_addr,
  324. + ap->ioaddr.ctl_addr);
  325. +}
  326. +
  327. +static int __devinit magicbox_cf_of_probe(struct of_device *op,
  328. + const struct of_device_id *match)
  329. +{
  330. + struct magicbox_cf_info *info;
  331. + struct ata_host *host;
  332. + int irq;
  333. + int ret = 0;
  334. +
  335. + info = kzalloc(sizeof(struct magicbox_cf_info), GFP_KERNEL);
  336. + if (info == NULL) {
  337. + ret = -ENOMEM;
  338. + goto err_exit;
  339. + }
  340. +
  341. + irq = irq_of_parse_and_map(op->node, 0);
  342. + if (irq < 0) {
  343. + dev_err(&op->dev, "invalid irq\n");
  344. + ret = -EINVAL;
  345. + goto err_free_info;
  346. + }
  347. +
  348. + info->base = of_iomap(op->node, 0);
  349. + if (info->base == NULL) {
  350. + ret = -ENOMEM;
  351. + goto err_free_info;
  352. + }
  353. +
  354. + info->ctrl = of_iomap(op->node, 1);
  355. + if (info->ctrl == NULL) {
  356. + ret = -ENOMEM;
  357. + goto err_unmap_base;
  358. + }
  359. +
  360. + host = ata_host_alloc(&op->dev, MAGICBOX_CF_MAXPORTS);
  361. + if (host == NULL) {
  362. + ret = -ENOMEM;
  363. + goto err_unmap_ctrl;
  364. + }
  365. +
  366. + host->private_data = info;
  367. + magicbox_cf_setup_port(host);
  368. +
  369. + ret = ata_host_activate(host, irq, ata_sff_interrupt,
  370. + IRQF_TRIGGER_RISING, &magicbox_cf_sht);
  371. + if (ret)
  372. + goto err_unmap_ctrl;
  373. +
  374. + dev_set_drvdata(&op->dev, host);
  375. + return 0;
  376. +
  377. + err_unmap_ctrl:
  378. + iounmap(info->ctrl);
  379. + err_unmap_base:
  380. + iounmap(info->base);
  381. + err_free_info:
  382. + kfree(info);
  383. + err_exit:
  384. + return ret;
  385. +}
  386. +
  387. +static __devexit int magicbox_cf_of_remove(struct of_device *op)
  388. +{
  389. + struct ata_host *host = dev_get_drvdata(&op->dev);
  390. + struct magicbox_cf_info *info = host->private_data;
  391. +
  392. + ata_host_detach(host);
  393. + iounmap(info->ctrl);
  394. + iounmap(info->base);
  395. + kfree(info);
  396. +
  397. + return 0;
  398. +}
  399. +
  400. +static struct of_device_id magicbox_cf_of_match[] = {
  401. + { .compatible = "pata-magicbox-cf", },
  402. + {},
  403. +};
  404. +
  405. +static struct of_platform_driver magicbox_cf_of_platform_driver = {
  406. + .owner = THIS_MODULE,
  407. + .name = DRV_NAME,
  408. + .match_table = magicbox_cf_of_match,
  409. + .probe = magicbox_cf_of_probe,
  410. + .remove = __devexit_p(magicbox_cf_of_remove),
  411. + .driver = {
  412. + .name = DRV_NAME,
  413. + .owner = THIS_MODULE,
  414. + },
  415. +};
  416. +
  417. +static int __init magicbox_cf_init(void)
  418. +{
  419. + return of_register_platform_driver(&magicbox_cf_of_platform_driver);
  420. +}
  421. +
  422. +static void __exit magicbox_cf_exit(void)
  423. +{
  424. + of_unregister_platform_driver(&magicbox_cf_of_platform_driver);
  425. +}
  426. +
  427. +module_init(magicbox_cf_init);
  428. +module_exit(magicbox_cf_exit);
  429. +
  430. +MODULE_DESCRIPTION(DRV_DESC);
  431. +MODULE_AUTHOR("Gabor Juhos <[email protected]>");
  432. +MODULE_LICENSE("GPL v2");
  433. +MODULE_VERSION(DRV_VERSION);
  434. +MODULE_DEVICE_TABLE(of, magicbox_cf_of_match);