palm_bk3710.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /*
  2. * Palmchip bk3710 IDE controller
  3. *
  4. * Copyright (C) 2006 Texas Instruments.
  5. * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
  6. *
  7. * ----------------------------------------------------------------------------
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22. * ----------------------------------------------------------------------------
  23. *
  24. */
  25. #include <linux/types.h>
  26. #include <linux/module.h>
  27. #include <linux/kernel.h>
  28. #include <linux/ioport.h>
  29. #include <linux/hdreg.h>
  30. #include <linux/ide.h>
  31. #include <linux/delay.h>
  32. #include <linux/init.h>
  33. #include <linux/clk.h>
  34. #include <linux/platform_device.h>
  35. /* Offset of the primary interface registers */
  36. #define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0
  37. /* Primary Control Offset */
  38. #define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6
  39. /*
  40. * PalmChip 3710 IDE Controller UDMA timing structure Definition
  41. */
  42. struct palm_bk3710_udmatiming {
  43. unsigned int rptime; /* Ready to pause time */
  44. unsigned int cycletime; /* Cycle Time */
  45. };
  46. #define BK3710_BMICP 0x00
  47. #define BK3710_BMISP 0x02
  48. #define BK3710_BMIDTP 0x04
  49. #define BK3710_BMICS 0x08
  50. #define BK3710_BMISS 0x0A
  51. #define BK3710_BMIDTS 0x0C
  52. #define BK3710_IDETIMP 0x40
  53. #define BK3710_IDETIMS 0x42
  54. #define BK3710_SIDETIM 0x44
  55. #define BK3710_SLEWCTL 0x45
  56. #define BK3710_IDESTATUS 0x47
  57. #define BK3710_UDMACTL 0x48
  58. #define BK3710_UDMATIM 0x4A
  59. #define BK3710_MISCCTL 0x50
  60. #define BK3710_REGSTB 0x54
  61. #define BK3710_REGRCVR 0x58
  62. #define BK3710_DATSTB 0x5C
  63. #define BK3710_DATRCVR 0x60
  64. #define BK3710_DMASTB 0x64
  65. #define BK3710_DMARCVR 0x68
  66. #define BK3710_UDMASTB 0x6C
  67. #define BK3710_UDMATRP 0x70
  68. #define BK3710_UDMAENV 0x74
  69. #define BK3710_IORDYTMP 0x78
  70. #define BK3710_IORDYTMS 0x7C
  71. #include "../ide-timing.h"
  72. static long ide_palm_clk;
  73. static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
  74. {160, 240}, /* UDMA Mode 0 */
  75. {125, 160}, /* UDMA Mode 1 */
  76. {100, 120}, /* UDMA Mode 2 */
  77. {100, 90}, /* UDMA Mode 3 */
  78. {85, 60}, /* UDMA Mode 4 */
  79. };
  80. static struct clk *ideclkp;
  81. static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
  82. unsigned int mode)
  83. {
  84. u8 tenv, trp, t0;
  85. u32 val32;
  86. u16 val16;
  87. /* DMA Data Setup */
  88. t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime,
  89. ide_palm_clk) - 1;
  90. tenv = DIV_ROUND_UP(20, ide_palm_clk) - 1;
  91. trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime,
  92. ide_palm_clk) - 1;
  93. /* udmatim Register */
  94. val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
  95. val16 |= (mode << (dev ? 4 : 0));
  96. writew(val16, base + BK3710_UDMATIM);
  97. /* udmastb Ultra DMA Access Strobe Width */
  98. val32 = readl(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
  99. val32 |= (t0 << (dev ? 8 : 0));
  100. writel(val32, base + BK3710_UDMASTB);
  101. /* udmatrp Ultra DMA Ready to Pause Time */
  102. val32 = readl(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
  103. val32 |= (trp << (dev ? 8 : 0));
  104. writel(val32, base + BK3710_UDMATRP);
  105. /* udmaenv Ultra DMA envelop Time */
  106. val32 = readl(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
  107. val32 |= (tenv << (dev ? 8 : 0));
  108. writel(val32, base + BK3710_UDMAENV);
  109. /* Enable UDMA for Device */
  110. val16 = readw(base + BK3710_UDMACTL) | (1 << dev);
  111. writew(val16, base + BK3710_UDMACTL);
  112. }
  113. static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
  114. unsigned short min_cycle,
  115. unsigned int mode)
  116. {
  117. u8 td, tkw, t0;
  118. u32 val32;
  119. u16 val16;
  120. struct ide_timing *t;
  121. int cycletime;
  122. t = ide_timing_find_mode(mode);
  123. cycletime = max_t(int, t->cycle, min_cycle);
  124. /* DMA Data Setup */
  125. t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
  126. td = DIV_ROUND_UP(t->active, ide_palm_clk);
  127. tkw = t0 - td - 1;
  128. td -= 1;
  129. val32 = readl(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
  130. val32 |= (td << (dev ? 8 : 0));
  131. writel(val32, base + BK3710_DMASTB);
  132. val32 = readl(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
  133. val32 |= (tkw << (dev ? 8 : 0));
  134. writel(val32, base + BK3710_DMARCVR);
  135. /* Disable UDMA for Device */
  136. val16 = readw(base + BK3710_UDMACTL) & ~(1 << dev);
  137. writew(val16, base + BK3710_UDMACTL);
  138. }
  139. static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
  140. unsigned int dev, unsigned int cycletime,
  141. unsigned int mode)
  142. {
  143. u8 t2, t2i, t0;
  144. u32 val32;
  145. struct ide_timing *t;
  146. /* PIO Data Setup */
  147. t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
  148. t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active,
  149. ide_palm_clk);
  150. t2i = t0 - t2 - 1;
  151. t2 -= 1;
  152. val32 = readl(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
  153. val32 |= (t2 << (dev ? 8 : 0));
  154. writel(val32, base + BK3710_DATSTB);
  155. val32 = readl(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
  156. val32 |= (t2i << (dev ? 8 : 0));
  157. writel(val32, base + BK3710_DATRCVR);
  158. if (mate && mate->present) {
  159. u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
  160. if (mode2 < mode)
  161. mode = mode2;
  162. }
  163. /* TASKFILE Setup */
  164. t = ide_timing_find_mode(XFER_PIO_0 + mode);
  165. t0 = DIV_ROUND_UP(t->cyc8b, ide_palm_clk);
  166. t2 = DIV_ROUND_UP(t->act8b, ide_palm_clk);
  167. t2i = t0 - t2 - 1;
  168. t2 -= 1;
  169. val32 = readl(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
  170. val32 |= (t2 << (dev ? 8 : 0));
  171. writel(val32, base + BK3710_REGSTB);
  172. val32 = readl(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
  173. val32 |= (t2i << (dev ? 8 : 0));
  174. writel(val32, base + BK3710_REGRCVR);
  175. }
  176. static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
  177. {
  178. int is_slave = drive->dn & 1;
  179. void __iomem *base = (void *)drive->hwif->dma_base;
  180. if (xferspeed >= XFER_UDMA_0) {
  181. palm_bk3710_setudmamode(base, is_slave,
  182. xferspeed - XFER_UDMA_0);
  183. } else {
  184. palm_bk3710_setdmamode(base, is_slave, drive->id->eide_dma_min,
  185. xferspeed);
  186. }
  187. }
  188. static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
  189. {
  190. unsigned int cycle_time;
  191. int is_slave = drive->dn & 1;
  192. ide_drive_t *mate;
  193. void __iomem *base = (void *)drive->hwif->dma_base;
  194. /*
  195. * Obtain the drive PIO data for tuning the Palm Chip registers
  196. */
  197. cycle_time = ide_pio_cycle_time(drive, pio);
  198. mate = ide_get_paired_drive(drive);
  199. palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
  200. }
  201. static void __devinit palm_bk3710_chipinit(void __iomem *base)
  202. {
  203. /*
  204. * enable the reset_en of ATA controller so that when ata signals
  205. * are brought out, by writing into device config. at that
  206. * time por_n signal should not be 'Z' and have a stable value.
  207. */
  208. writel(0x0300, base + BK3710_MISCCTL);
  209. /* wait for some time and deassert the reset of ATA Device. */
  210. mdelay(100);
  211. /* Deassert the Reset */
  212. writel(0x0200, base + BK3710_MISCCTL);
  213. /*
  214. * Program the IDETIMP Register Value based on the following assumptions
  215. *
  216. * (ATA_IDETIMP_IDEEN , ENABLE ) |
  217. * (ATA_IDETIMP_SLVTIMEN , DISABLE) |
  218. * (ATA_IDETIMP_RDYSMPL , 70NS) |
  219. * (ATA_IDETIMP_RDYRCVRY , 50NS) |
  220. * (ATA_IDETIMP_DMAFTIM1 , PIOCOMP) |
  221. * (ATA_IDETIMP_PREPOST1 , DISABLE) |
  222. * (ATA_IDETIMP_RDYSEN1 , DISABLE) |
  223. * (ATA_IDETIMP_PIOFTIM1 , DISABLE) |
  224. * (ATA_IDETIMP_DMAFTIM0 , PIOCOMP) |
  225. * (ATA_IDETIMP_PREPOST0 , DISABLE) |
  226. * (ATA_IDETIMP_RDYSEN0 , DISABLE) |
  227. * (ATA_IDETIMP_PIOFTIM0 , DISABLE)
  228. */
  229. writew(0xB388, base + BK3710_IDETIMP);
  230. /*
  231. * Configure SIDETIM Register
  232. * (ATA_SIDETIM_RDYSMPS1 ,120NS ) |
  233. * (ATA_SIDETIM_RDYRCYS1 ,120NS )
  234. */
  235. writeb(0, base + BK3710_SIDETIM);
  236. /*
  237. * UDMACTL Ultra-ATA DMA Control
  238. * (ATA_UDMACTL_UDMAP1 , 0 ) |
  239. * (ATA_UDMACTL_UDMAP0 , 0 )
  240. *
  241. */
  242. writew(0, base + BK3710_UDMACTL);
  243. /*
  244. * MISCCTL Miscellaneous Conrol Register
  245. * (ATA_MISCCTL_RSTMODEP , 1) |
  246. * (ATA_MISCCTL_RESETP , 0) |
  247. * (ATA_MISCCTL_TIMORIDE , 1)
  248. */
  249. writel(0x201, base + BK3710_MISCCTL);
  250. /*
  251. * IORDYTMP IORDY Timer for Primary Register
  252. * (ATA_IORDYTMP_IORDYTMP , 0xffff )
  253. */
  254. writel(0xFFFF, base + BK3710_IORDYTMP);
  255. /*
  256. * Configure BMISP Register
  257. * (ATA_BMISP_DMAEN1 , DISABLE ) |
  258. * (ATA_BMISP_DMAEN0 , DISABLE ) |
  259. * (ATA_BMISP_IORDYINT , CLEAR) |
  260. * (ATA_BMISP_INTRSTAT , CLEAR) |
  261. * (ATA_BMISP_DMAERROR , CLEAR)
  262. */
  263. writew(0, base + BK3710_BMISP);
  264. palm_bk3710_setpiomode(base, NULL, 0, 600, 0);
  265. palm_bk3710_setpiomode(base, NULL, 1, 600, 0);
  266. }
  267. static u8 __devinit palm_bk3710_cable_detect(ide_hwif_t *hwif)
  268. {
  269. return ATA_CBL_PATA80;
  270. }
  271. static void __devinit palm_bk3710_init_hwif(ide_hwif_t *hwif)
  272. {
  273. hwif->set_pio_mode = palm_bk3710_set_pio_mode;
  274. hwif->set_dma_mode = palm_bk3710_set_dma_mode;
  275. hwif->cable_detect = palm_bk3710_cable_detect;
  276. }
  277. static const struct ide_port_info __devinitdata palm_bk3710_port_info = {
  278. .init_hwif = palm_bk3710_init_hwif,
  279. .host_flags = IDE_HFLAG_NO_DMA, /* hack (no PCI) */
  280. .pio_mask = ATA_PIO4,
  281. .udma_mask = ATA_UDMA4, /* (input clk 99MHz) */
  282. .mwdma_mask = ATA_MWDMA2,
  283. };
  284. static int __devinit palm_bk3710_probe(struct platform_device *pdev)
  285. {
  286. struct clk *clkp;
  287. struct resource *mem, *irq;
  288. ide_hwif_t *hwif;
  289. void __iomem *base;
  290. int pribase, i;
  291. hw_regs_t hw;
  292. u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
  293. clkp = clk_get(NULL, "IDECLK");
  294. if (IS_ERR(clkp))
  295. return -ENODEV;
  296. ideclkp = clkp;
  297. clk_enable(ideclkp);
  298. ide_palm_clk = clk_get_rate(ideclkp)/100000;
  299. ide_palm_clk = (10000/ide_palm_clk) + 1;
  300. /* Register the IDE interface with Linux ATA Interface */
  301. memset(&hw, 0, sizeof(hw));
  302. mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  303. if (mem == NULL) {
  304. printk(KERN_ERR "failed to get memory region resource\n");
  305. return -ENODEV;
  306. }
  307. irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  308. if (irq == NULL) {
  309. printk(KERN_ERR "failed to get IRQ resource\n");
  310. return -ENODEV;
  311. }
  312. base = (void *)mem->start;
  313. /* Configure the Palm Chip controller */
  314. palm_bk3710_chipinit(base);
  315. pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
  316. for (i = 0; i < IDE_NR_PORTS - 2; i++)
  317. hw.io_ports[i] = pribase + i;
  318. hw.io_ports[IDE_CONTROL_OFFSET] = mem->start +
  319. IDE_PALM_ATA_PRI_CTL_OFFSET;
  320. hw.irq = irq->start;
  321. hw.chipset = ide_palm3710;
  322. hwif = ide_find_port();
  323. if (hwif == NULL)
  324. goto out;
  325. i = hwif->index;
  326. if (hwif->present)
  327. ide_unregister(i);
  328. else
  329. ide_init_port_data(hwif, i);
  330. ide_init_port_hw(hwif, &hw);
  331. hwif->mmio = 1;
  332. default_hwif_mmiops(hwif);
  333. ide_setup_dma(hwif, mem->start);
  334. idx[0] = i;
  335. ide_device_add(idx, &palm_bk3710_port_info);
  336. if (!hwif->present)
  337. goto out;
  338. return 0;
  339. out:
  340. printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
  341. return -ENODEV;
  342. }
  343. /* work with hotplug and coldplug */
  344. MODULE_ALIAS("platform:palm_bk3710");
  345. static struct platform_driver platform_bk_driver = {
  346. .driver = {
  347. .name = "palm_bk3710",
  348. .owner = THIS_MODULE,
  349. },
  350. .probe = palm_bk3710_probe,
  351. .remove = NULL,
  352. };
  353. static int __init palm_bk3710_init(void)
  354. {
  355. return platform_driver_register(&platform_bk_driver);
  356. }
  357. module_init(palm_bk3710_init);
  358. MODULE_LICENSE("GPL");