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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. --- a/drivers/ata/Kconfig
  2. +++ b/drivers/ata/Kconfig
  3. @@ -234,6 +234,16 @@ config PDC_ADMA
  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 CAVIUM_OCTEON_SOC
  18. --- a/drivers/ata/Makefile
  19. +++ b/drivers/ata/Makefile
  20. @@ -91,6 +91,7 @@ obj-$(CONFIG_PATA_AT91) += pata_at91.o
  21. obj-$(CONFIG_PATA_CMD640_PCI) += pata_cmd640.o
  22. obj-$(CONFIG_PATA_ISAPNP) += pata_isapnp.o
  23. obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o
  24. +obj-$(CONFIG_PATA_MAGICBOX_CF) += pata_magicbox_cf.o
  25. obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o
  26. obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o
  27. obj-$(CONFIG_PATA_OPTI) += pata_opti.o
  28. --- /dev/null
  29. +++ b/drivers/ata/pata_magicbox_cf.c
  30. @@ -0,0 +1,401 @@
  31. +/*
  32. + * PATA/CompactFlash driver for the MagicBox v2/OpenRB boards.
  33. + *
  34. + * Copyright (C) 2009,2012 Gabor Juhos <juhosg@openwrt.org>
  35. + *
  36. + * Based on the IDE driver by Wojtek Kaniewski <wojtekka@toxygen.net>
  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/slab.h>
  46. +#include <linux/types.h>
  47. +#include <linux/ioport.h>
  48. +#include <linux/libata.h>
  49. +#include <linux/irq.h>
  50. +//#include <linux/of.h>
  51. +//#include <linux/of_device.h>
  52. +#include <linux/of_platform.h>
  53. +#include <scsi/scsi_host.h>
  54. +
  55. +#define DRV_DESC "PATA/CompactFlash driver for Magicbox/OpenRB boards"
  56. +#define DRV_NAME "pata_magicbox_cf"
  57. +#define DRV_VERSION "0.1.0"
  58. +
  59. +#define MAGICBOX_CF_REG_CMD (2 * ATA_REG_CMD)
  60. +#define MAGICBOX_CF_REG_DATA (2 * ATA_REG_DATA)
  61. +#define MAGICBOX_CF_REG_ERR (2 * ATA_REG_ERR)
  62. +#define MAGICBOX_CF_REG_FEATURE (2 * ATA_REG_FEATURE)
  63. +#define MAGICBOX_CF_REG_NSECT (2 * ATA_REG_NSECT)
  64. +#define MAGICBOX_CF_REG_LBAL (2 * ATA_REG_LBAL)
  65. +#define MAGICBOX_CF_REG_LBAM (2 * ATA_REG_LBAM)
  66. +#define MAGICBOX_CF_REG_LBAH (2 * ATA_REG_LBAH)
  67. +#define MAGICBOX_CF_REG_DEVICE (2 * ATA_REG_DEVICE)
  68. +#define MAGICBOX_CF_REG_STATUS (2 * ATA_REG_STATUS)
  69. +#define MAGICBOX_CF_REG_ALTSTATUS (2 * 6)
  70. +#define MAGICBOX_CF_REG_CTL (2 * 6)
  71. +
  72. +#define MAGICBOX_CF_MAXPORTS 1
  73. +
  74. +struct magicbox_cf_info {
  75. + void __iomem *base;
  76. + void __iomem *ctrl;
  77. +};
  78. +
  79. +static inline u8 magicbox_cf_inb(void __iomem *port)
  80. +{
  81. + return (u8) (readw(port) >> 8) & 0xff;
  82. +}
  83. +
  84. +static inline void magicbox_cf_outb(void __iomem *port, u8 value)
  85. +{
  86. + writew(value << 8, port);
  87. +}
  88. +
  89. +static int magicbox_cf_set_mode(struct ata_link *link,
  90. + struct ata_device **error)
  91. +{
  92. + struct ata_device *dev;
  93. +
  94. + ata_for_each_dev(dev, link, ENABLED) {
  95. + ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n");
  96. + dev->pio_mode = XFER_PIO_0;
  97. + dev->xfer_mode = XFER_PIO_0;
  98. + dev->xfer_shift = ATA_SHIFT_PIO;
  99. + dev->flags |= ATA_DFLAG_PIO;
  100. + }
  101. +
  102. + return 0;
  103. +}
  104. +
  105. +static void magicbox_cf_exec_command(struct ata_port *ap,
  106. + const struct ata_taskfile *tf)
  107. +{
  108. + DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
  109. +
  110. + magicbox_cf_outb(ap->ioaddr.command_addr, tf->command);
  111. + ata_sff_pause(ap);
  112. +}
  113. +
  114. +static u8 magicbox_cf_check_status(struct ata_port *ap)
  115. +{
  116. + u8 status;
  117. +
  118. + status = magicbox_cf_inb(ap->ioaddr.status_addr);
  119. +
  120. + DPRINTK("ata%u: status 0x%X, from %p\n", ap->print_id, status,
  121. + ap->ioaddr.status_addr);
  122. +
  123. + return status;
  124. +}
  125. +
  126. +static u8 magicbox_cf_check_altstatus(struct ata_port *ap)
  127. +{
  128. + u8 altstatus;
  129. +
  130. + altstatus = magicbox_cf_inb(ap->ioaddr.altstatus_addr);
  131. +
  132. + DPRINTK("ata%u: altstatus 0x%X, from %p\n", ap->print_id,
  133. + altstatus, ap->ioaddr.altstatus_addr);
  134. +
  135. + return altstatus;
  136. +}
  137. +
  138. +static void magicbox_cf_dev_select(struct ata_port *ap, unsigned int device)
  139. +{
  140. + /* Nothing to do. We are supporting one device only. */
  141. +}
  142. +
  143. +static void magicbox_cf_tf_load(struct ata_port *ap,
  144. + const struct ata_taskfile *tf)
  145. +{
  146. + struct ata_ioports *ioaddr = &ap->ioaddr;
  147. + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
  148. +
  149. + if (tf->ctl != ap->last_ctl) {
  150. + magicbox_cf_outb(ioaddr->ctl_addr, tf->ctl);
  151. + ap->last_ctl = tf->ctl;
  152. + ata_wait_idle(ap);
  153. + }
  154. +
  155. + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
  156. + magicbox_cf_outb(ioaddr->feature_addr, tf->hob_feature);
  157. + magicbox_cf_outb(ioaddr->nsect_addr, tf->hob_nsect);
  158. + magicbox_cf_outb(ioaddr->lbal_addr, tf->hob_lbal);
  159. + magicbox_cf_outb(ioaddr->lbam_addr, tf->hob_lbam);
  160. + magicbox_cf_outb(ioaddr->lbah_addr, tf->hob_lbah);
  161. + VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
  162. + tf->hob_feature,
  163. + tf->hob_nsect,
  164. + tf->hob_lbal,
  165. + tf->hob_lbam,
  166. + tf->hob_lbah);
  167. + }
  168. +
  169. + if (is_addr) {
  170. + magicbox_cf_outb(ioaddr->feature_addr, tf->feature);
  171. + magicbox_cf_outb(ioaddr->nsect_addr, tf->nsect);
  172. + magicbox_cf_outb(ioaddr->lbal_addr, tf->lbal);
  173. + magicbox_cf_outb(ioaddr->lbam_addr, tf->lbam);
  174. + magicbox_cf_outb(ioaddr->lbah_addr, tf->lbah);
  175. + VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
  176. + tf->feature,
  177. + tf->nsect,
  178. + tf->lbal,
  179. + tf->lbam,
  180. + tf->lbah);
  181. + }
  182. +
  183. + if (tf->flags & ATA_TFLAG_DEVICE) {
  184. + magicbox_cf_outb(ioaddr->device_addr, tf->device);
  185. + VPRINTK("device 0x%X\n", tf->device);
  186. + }
  187. +
  188. + ata_wait_idle(ap);
  189. +}
  190. +
  191. +static void magicbox_cf_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
  192. +{
  193. + struct ata_ioports *ioaddr = &ap->ioaddr;
  194. +
  195. + tf->command = magicbox_cf_inb(ap->ioaddr.status_addr);
  196. + tf->feature = magicbox_cf_inb(ioaddr->error_addr);
  197. + tf->nsect = magicbox_cf_inb(ioaddr->nsect_addr);
  198. + tf->lbal = magicbox_cf_inb(ioaddr->lbal_addr);
  199. + tf->lbam = magicbox_cf_inb(ioaddr->lbam_addr);
  200. + tf->lbah = magicbox_cf_inb(ioaddr->lbah_addr);
  201. + tf->device = magicbox_cf_inb(ioaddr->device_addr);
  202. + VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
  203. + tf->feature,
  204. + tf->nsect,
  205. + tf->lbal,
  206. + tf->lbam,
  207. + tf->lbah);
  208. +
  209. + if (tf->flags & ATA_TFLAG_LBA48) {
  210. + magicbox_cf_outb(ioaddr->ctl_addr, tf->ctl | ATA_HOB);
  211. + tf->hob_feature = magicbox_cf_inb(ioaddr->error_addr);
  212. + tf->hob_nsect = magicbox_cf_inb(ioaddr->nsect_addr);
  213. + tf->hob_lbal = magicbox_cf_inb(ioaddr->lbal_addr);
  214. + tf->hob_lbam = magicbox_cf_inb(ioaddr->lbam_addr);
  215. + tf->hob_lbah = magicbox_cf_inb(ioaddr->lbah_addr);
  216. + magicbox_cf_outb(ioaddr->ctl_addr, tf->ctl);
  217. + ap->last_ctl = tf->ctl;
  218. + VPRINTK("hob: feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
  219. + tf->feature,
  220. + tf->nsect,
  221. + tf->lbal,
  222. + tf->lbam,
  223. + tf->lbah);
  224. + }
  225. +}
  226. +
  227. +static unsigned int magicbox_cf_data_xfer(struct ata_device *dev,
  228. + unsigned char *buf,
  229. + unsigned int buflen, int rw)
  230. +{
  231. + struct ata_port *ap = dev->link->ap;
  232. + unsigned int words = buflen >> 1;
  233. + unsigned int i;
  234. + u16 *buf16 = (u16 *) buf;
  235. + void __iomem *mmio = ap->ioaddr.data_addr;
  236. +
  237. + /* Transfer multiple of 2 bytes */
  238. + if (rw == READ)
  239. + for (i = 0; i < words; i++)
  240. + buf16[i] = readw(mmio);
  241. + else
  242. + for (i = 0; i < words; i++)
  243. + writew(buf16[i], mmio);
  244. +
  245. + /* Transfer trailing 1 byte, if any. */
  246. + if (unlikely(buflen & 0x01)) {
  247. + u16 align_buf[1] = { 0 };
  248. + unsigned char *trailing_buf = buf + buflen - 1;
  249. +
  250. + if (rw == READ) {
  251. + align_buf[0] = readw(mmio);
  252. + memcpy(trailing_buf, align_buf, 1);
  253. + } else {
  254. + memcpy(align_buf, trailing_buf, 1);
  255. + writew(align_buf[0], mmio);
  256. + }
  257. + words++;
  258. + }
  259. +
  260. + return words << 1;
  261. +}
  262. +
  263. +static void magicbox_cf_irq_on(struct ata_port *ap)
  264. +{
  265. + /* Nothing to do. */
  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_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 magicbox_cf_of_probe(struct platform_device *op)
  328. +{
  329. + struct magicbox_cf_info *info;
  330. + struct ata_host *host;
  331. + int irq;
  332. + int ret = 0;
  333. +
  334. + info = kzalloc(sizeof(struct magicbox_cf_info), GFP_KERNEL);
  335. + if (info == NULL) {
  336. + ret = -ENOMEM;
  337. + goto err_exit;
  338. + }
  339. +
  340. + irq = irq_of_parse_and_map(op->dev.of_node, 0);
  341. + if (irq < 0) {
  342. + dev_err(&op->dev, "invalid irq\n");
  343. + ret = -EINVAL;
  344. + goto err_free_info;
  345. + }
  346. +
  347. + info->base = of_iomap(op->dev.of_node, 0);
  348. + if (info->base == NULL) {
  349. + ret = -ENOMEM;
  350. + goto err_free_info;
  351. + }
  352. +
  353. + info->ctrl = of_iomap(op->dev.of_node, 1);
  354. + if (info->ctrl == NULL) {
  355. + ret = -ENOMEM;
  356. + goto err_unmap_base;
  357. + }
  358. +
  359. + host = ata_host_alloc(&op->dev, MAGICBOX_CF_MAXPORTS);
  360. + if (host == NULL) {
  361. + ret = -ENOMEM;
  362. + goto err_unmap_ctrl;
  363. + }
  364. +
  365. + host->private_data = info;
  366. + magicbox_cf_setup_port(host);
  367. +
  368. + ret = ata_host_activate(host, irq, ata_sff_interrupt,
  369. + IRQF_TRIGGER_RISING, &magicbox_cf_sht);
  370. + if (ret)
  371. + goto err_unmap_ctrl;
  372. +
  373. + dev_set_drvdata(&op->dev, host);
  374. + return 0;
  375. +
  376. + err_unmap_ctrl:
  377. + iounmap(info->ctrl);
  378. + err_unmap_base:
  379. + iounmap(info->base);
  380. + err_free_info:
  381. + kfree(info);
  382. + err_exit:
  383. + return ret;
  384. +}
  385. +
  386. +static int magicbox_cf_of_remove(struct platform_device *op)
  387. +{
  388. + struct ata_host *host = dev_get_drvdata(&op->dev);
  389. + struct magicbox_cf_info *info = host->private_data;
  390. +
  391. + ata_host_detach(host);
  392. + iounmap(info->ctrl);
  393. + iounmap(info->base);
  394. + kfree(info);
  395. +
  396. + return 0;
  397. +}
  398. +
  399. +static struct of_device_id magicbox_cf_of_match[] = {
  400. + { .compatible = "pata-magicbox-cf", },
  401. + {},
  402. +};
  403. +
  404. +static struct platform_driver magicbox_cf_of_platform_driver = {
  405. + .probe = magicbox_cf_of_probe,
  406. + .remove = magicbox_cf_of_remove,
  407. + .driver = {
  408. + .name = DRV_NAME,
  409. + .owner = THIS_MODULE,
  410. + .of_match_table = magicbox_cf_of_match,
  411. + },
  412. +};
  413. +
  414. +static int __init magicbox_cf_init(void)
  415. +{
  416. + return platform_driver_register(&magicbox_cf_of_platform_driver);
  417. +}
  418. +
  419. +static void __exit magicbox_cf_exit(void)
  420. +{
  421. + platform_driver_unregister(&magicbox_cf_of_platform_driver);
  422. +}
  423. +
  424. +module_init(magicbox_cf_init);
  425. +module_exit(magicbox_cf_exit);
  426. +
  427. +MODULE_DESCRIPTION(DRV_DESC);
  428. +MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
  429. +MODULE_LICENSE("GPL v2");
  430. +MODULE_VERSION(DRV_VERSION);
  431. +MODULE_DEVICE_TABLE(of, magicbox_cf_of_match);