board-omapl138-hawk.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. /*
  2. * Hawkboard.org based on TI's OMAP-L138 Platform
  3. *
  4. * Initial code: Syed Mohammed Khasim
  5. *
  6. * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com
  7. *
  8. * This file is licensed under the terms of the GNU General Public License
  9. * version 2. This program is licensed "as is" without any warranty of
  10. * any kind, whether express or implied.
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/init.h>
  14. #include <linux/console.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/gpio.h>
  17. #include <linux/gpio/machine.h>
  18. #include <linux/mtd/partitions.h>
  19. #include <linux/mtd/rawnand.h>
  20. #include <linux/platform_data/gpio-davinci.h>
  21. #include <linux/platform_data/mtd-davinci.h>
  22. #include <linux/platform_data/mtd-davinci-aemif.h>
  23. #include <linux/platform_data/ti-aemif.h>
  24. #include <linux/regulator/machine.h>
  25. #include <asm/mach-types.h>
  26. #include <asm/mach/arch.h>
  27. #include <mach/common.h>
  28. #include "cp_intc.h"
  29. #include <mach/da8xx.h>
  30. #include <mach/mux.h>
  31. #define HAWKBOARD_PHY_ID "davinci_mdio-0:07"
  32. #define DA850_USB1_VBUS_PIN GPIO_TO_PIN(2, 4)
  33. #define DA850_USB1_OC_PIN GPIO_TO_PIN(6, 13)
  34. static short omapl138_hawk_mii_pins[] __initdata = {
  35. DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3,
  36. DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
  37. DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
  38. DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
  39. DA850_MDIO_D,
  40. -1
  41. };
  42. static __init void omapl138_hawk_config_emac(void)
  43. {
  44. void __iomem *cfgchip3 = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG);
  45. int ret;
  46. u32 val;
  47. struct davinci_soc_info *soc_info = &davinci_soc_info;
  48. val = __raw_readl(cfgchip3);
  49. val &= ~BIT(8);
  50. ret = davinci_cfg_reg_list(omapl138_hawk_mii_pins);
  51. if (ret) {
  52. pr_warn("%s: CPGMAC/MII mux setup failed: %d\n", __func__, ret);
  53. return;
  54. }
  55. /* configure the CFGCHIP3 register for MII */
  56. __raw_writel(val, cfgchip3);
  57. pr_info("EMAC: MII PHY configured\n");
  58. soc_info->emac_pdata->phy_id = HAWKBOARD_PHY_ID;
  59. ret = da8xx_register_emac();
  60. if (ret)
  61. pr_warn("%s: EMAC registration failed: %d\n", __func__, ret);
  62. }
  63. /*
  64. * The following EDMA channels/slots are not being used by drivers (for
  65. * example: Timer, GPIO, UART events etc) on da850/omap-l138 EVM/Hawkboard,
  66. * hence they are being reserved for codecs on the DSP side.
  67. */
  68. static const s16 da850_dma0_rsv_chans[][2] = {
  69. /* (offset, number) */
  70. { 8, 6},
  71. {24, 4},
  72. {30, 2},
  73. {-1, -1}
  74. };
  75. static const s16 da850_dma0_rsv_slots[][2] = {
  76. /* (offset, number) */
  77. { 8, 6},
  78. {24, 4},
  79. {30, 50},
  80. {-1, -1}
  81. };
  82. static const s16 da850_dma1_rsv_chans[][2] = {
  83. /* (offset, number) */
  84. { 0, 28},
  85. {30, 2},
  86. {-1, -1}
  87. };
  88. static const s16 da850_dma1_rsv_slots[][2] = {
  89. /* (offset, number) */
  90. { 0, 28},
  91. {30, 90},
  92. {-1, -1}
  93. };
  94. static struct edma_rsv_info da850_edma_cc0_rsv = {
  95. .rsv_chans = da850_dma0_rsv_chans,
  96. .rsv_slots = da850_dma0_rsv_slots,
  97. };
  98. static struct edma_rsv_info da850_edma_cc1_rsv = {
  99. .rsv_chans = da850_dma1_rsv_chans,
  100. .rsv_slots = da850_dma1_rsv_slots,
  101. };
  102. static struct edma_rsv_info *da850_edma_rsv[2] = {
  103. &da850_edma_cc0_rsv,
  104. &da850_edma_cc1_rsv,
  105. };
  106. static const short hawk_mmcsd0_pins[] = {
  107. DA850_MMCSD0_DAT_0, DA850_MMCSD0_DAT_1, DA850_MMCSD0_DAT_2,
  108. DA850_MMCSD0_DAT_3, DA850_MMCSD0_CLK, DA850_MMCSD0_CMD,
  109. DA850_GPIO3_12, DA850_GPIO3_13,
  110. -1
  111. };
  112. #define DA850_HAWK_MMCSD_CD_PIN GPIO_TO_PIN(3, 12)
  113. #define DA850_HAWK_MMCSD_WP_PIN GPIO_TO_PIN(3, 13)
  114. static struct gpiod_lookup_table mmc_gpios_table = {
  115. .dev_id = "da830-mmc.0",
  116. .table = {
  117. GPIO_LOOKUP("davinci_gpio.0", DA850_HAWK_MMCSD_CD_PIN, "cd",
  118. GPIO_ACTIVE_LOW),
  119. GPIO_LOOKUP("davinci_gpio.0", DA850_HAWK_MMCSD_WP_PIN, "wp",
  120. GPIO_ACTIVE_LOW),
  121. },
  122. };
  123. static struct davinci_mmc_config da850_mmc_config = {
  124. .wires = 4,
  125. .max_freq = 50000000,
  126. .caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
  127. };
  128. static __init void omapl138_hawk_mmc_init(void)
  129. {
  130. int ret;
  131. ret = davinci_cfg_reg_list(hawk_mmcsd0_pins);
  132. if (ret) {
  133. pr_warn("%s: MMC/SD0 mux setup failed: %d\n", __func__, ret);
  134. return;
  135. }
  136. gpiod_add_lookup_table(&mmc_gpios_table);
  137. ret = da8xx_register_mmcsd0(&da850_mmc_config);
  138. if (ret) {
  139. pr_warn("%s: MMC/SD0 registration failed: %d\n", __func__, ret);
  140. goto mmc_setup_mmcsd_fail;
  141. }
  142. return;
  143. mmc_setup_mmcsd_fail:
  144. gpiod_remove_lookup_table(&mmc_gpios_table);
  145. }
  146. static struct mtd_partition omapl138_hawk_nandflash_partition[] = {
  147. {
  148. .name = "u-boot env",
  149. .offset = 0,
  150. .size = SZ_128K,
  151. .mask_flags = MTD_WRITEABLE,
  152. },
  153. {
  154. .name = "u-boot",
  155. .offset = MTDPART_OFS_APPEND,
  156. .size = SZ_512K,
  157. .mask_flags = MTD_WRITEABLE,
  158. },
  159. {
  160. .name = "free space",
  161. .offset = MTDPART_OFS_APPEND,
  162. .size = MTDPART_SIZ_FULL,
  163. .mask_flags = 0,
  164. },
  165. };
  166. static struct davinci_aemif_timing omapl138_hawk_nandflash_timing = {
  167. .wsetup = 24,
  168. .wstrobe = 21,
  169. .whold = 14,
  170. .rsetup = 19,
  171. .rstrobe = 50,
  172. .rhold = 0,
  173. .ta = 20,
  174. };
  175. static struct davinci_nand_pdata omapl138_hawk_nandflash_data = {
  176. .core_chipsel = 1,
  177. .parts = omapl138_hawk_nandflash_partition,
  178. .nr_parts = ARRAY_SIZE(omapl138_hawk_nandflash_partition),
  179. .ecc_mode = NAND_ECC_HW,
  180. .ecc_bits = 4,
  181. .bbt_options = NAND_BBT_USE_FLASH,
  182. .options = NAND_BUSWIDTH_16,
  183. .timing = &omapl138_hawk_nandflash_timing,
  184. .mask_chipsel = 0,
  185. .mask_ale = 0,
  186. .mask_cle = 0,
  187. };
  188. static struct resource omapl138_hawk_nandflash_resource[] = {
  189. {
  190. .start = DA8XX_AEMIF_CS3_BASE,
  191. .end = DA8XX_AEMIF_CS3_BASE + SZ_32M,
  192. .flags = IORESOURCE_MEM,
  193. },
  194. {
  195. .start = DA8XX_AEMIF_CTL_BASE,
  196. .end = DA8XX_AEMIF_CTL_BASE + SZ_32K,
  197. .flags = IORESOURCE_MEM,
  198. },
  199. };
  200. static struct resource omapl138_hawk_aemif_resource[] = {
  201. {
  202. .start = DA8XX_AEMIF_CTL_BASE,
  203. .end = DA8XX_AEMIF_CTL_BASE + SZ_32K,
  204. .flags = IORESOURCE_MEM,
  205. }
  206. };
  207. static struct aemif_abus_data omapl138_hawk_aemif_abus_data[] = {
  208. {
  209. .cs = 3,
  210. }
  211. };
  212. static struct platform_device omapl138_hawk_aemif_devices[] = {
  213. {
  214. .name = "davinci_nand",
  215. .id = -1,
  216. .dev = {
  217. .platform_data = &omapl138_hawk_nandflash_data,
  218. },
  219. .resource = omapl138_hawk_nandflash_resource,
  220. .num_resources = ARRAY_SIZE(omapl138_hawk_nandflash_resource),
  221. }
  222. };
  223. static struct aemif_platform_data omapl138_hawk_aemif_pdata = {
  224. .cs_offset = 2,
  225. .abus_data = omapl138_hawk_aemif_abus_data,
  226. .num_abus_data = ARRAY_SIZE(omapl138_hawk_aemif_abus_data),
  227. .sub_devices = omapl138_hawk_aemif_devices,
  228. .num_sub_devices = ARRAY_SIZE(omapl138_hawk_aemif_devices),
  229. };
  230. static struct platform_device omapl138_hawk_aemif_device = {
  231. .name = "ti-aemif",
  232. .id = -1,
  233. .dev = {
  234. .platform_data = &omapl138_hawk_aemif_pdata,
  235. },
  236. .resource = omapl138_hawk_aemif_resource,
  237. .num_resources = ARRAY_SIZE(omapl138_hawk_aemif_resource),
  238. };
  239. static const short omapl138_hawk_nand_pins[] = {
  240. DA850_EMA_WAIT_1, DA850_NEMA_OE, DA850_NEMA_WE, DA850_NEMA_CS_3,
  241. DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3,
  242. DA850_EMA_D_4, DA850_EMA_D_5, DA850_EMA_D_6, DA850_EMA_D_7,
  243. DA850_EMA_D_8, DA850_EMA_D_9, DA850_EMA_D_10, DA850_EMA_D_11,
  244. DA850_EMA_D_12, DA850_EMA_D_13, DA850_EMA_D_14, DA850_EMA_D_15,
  245. DA850_EMA_A_1, DA850_EMA_A_2,
  246. -1
  247. };
  248. static int omapl138_hawk_register_aemif(void)
  249. {
  250. int ret;
  251. ret = davinci_cfg_reg_list(omapl138_hawk_nand_pins);
  252. if (ret)
  253. pr_warn("%s: NAND mux setup failed: %d\n", __func__, ret);
  254. return platform_device_register(&omapl138_hawk_aemif_device);
  255. }
  256. static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id);
  257. static da8xx_ocic_handler_t hawk_usb_ocic_handler;
  258. static const short da850_hawk_usb11_pins[] = {
  259. DA850_GPIO2_4, DA850_GPIO6_13,
  260. -1
  261. };
  262. static int hawk_usb_set_power(unsigned port, int on)
  263. {
  264. gpio_set_value(DA850_USB1_VBUS_PIN, on);
  265. return 0;
  266. }
  267. static int hawk_usb_get_power(unsigned port)
  268. {
  269. return gpio_get_value(DA850_USB1_VBUS_PIN);
  270. }
  271. static int hawk_usb_get_oci(unsigned port)
  272. {
  273. return !gpio_get_value(DA850_USB1_OC_PIN);
  274. }
  275. static int hawk_usb_ocic_notify(da8xx_ocic_handler_t handler)
  276. {
  277. int irq = gpio_to_irq(DA850_USB1_OC_PIN);
  278. int error = 0;
  279. if (handler != NULL) {
  280. hawk_usb_ocic_handler = handler;
  281. error = request_irq(irq, omapl138_hawk_usb_ocic_irq,
  282. IRQF_TRIGGER_RISING |
  283. IRQF_TRIGGER_FALLING,
  284. "OHCI over-current indicator", NULL);
  285. if (error)
  286. pr_err("%s: could not request IRQ to watch "
  287. "over-current indicator changes\n", __func__);
  288. } else {
  289. free_irq(irq, NULL);
  290. }
  291. return error;
  292. }
  293. static struct da8xx_ohci_root_hub omapl138_hawk_usb11_pdata = {
  294. .set_power = hawk_usb_set_power,
  295. .get_power = hawk_usb_get_power,
  296. .get_oci = hawk_usb_get_oci,
  297. .ocic_notify = hawk_usb_ocic_notify,
  298. /* TPS2087 switch @ 5V */
  299. .potpgt = (3 + 1) / 2, /* 3 ms max */
  300. };
  301. static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id)
  302. {
  303. hawk_usb_ocic_handler(&omapl138_hawk_usb11_pdata, 1);
  304. return IRQ_HANDLED;
  305. }
  306. static __init void omapl138_hawk_usb_init(void)
  307. {
  308. int ret;
  309. ret = davinci_cfg_reg_list(da850_hawk_usb11_pins);
  310. if (ret) {
  311. pr_warn("%s: USB 1.1 PinMux setup failed: %d\n", __func__, ret);
  312. return;
  313. }
  314. ret = da8xx_register_usb_phy_clocks();
  315. if (ret)
  316. pr_warn("%s: USB PHY CLK registration failed: %d\n",
  317. __func__, ret);
  318. ret = da8xx_register_usb_phy();
  319. if (ret)
  320. pr_warn("%s: USB PHY registration failed: %d\n",
  321. __func__, ret);
  322. ret = gpio_request_one(DA850_USB1_VBUS_PIN,
  323. GPIOF_DIR_OUT, "USB1 VBUS");
  324. if (ret < 0) {
  325. pr_err("%s: failed to request GPIO for USB 1.1 port "
  326. "power control: %d\n", __func__, ret);
  327. return;
  328. }
  329. ret = gpio_request_one(DA850_USB1_OC_PIN,
  330. GPIOF_DIR_IN, "USB1 OC");
  331. if (ret < 0) {
  332. pr_err("%s: failed to request GPIO for USB 1.1 port "
  333. "over-current indicator: %d\n", __func__, ret);
  334. goto usb11_setup_oc_fail;
  335. }
  336. ret = da8xx_register_usb11(&omapl138_hawk_usb11_pdata);
  337. if (ret) {
  338. pr_warn("%s: USB 1.1 registration failed: %d\n", __func__, ret);
  339. goto usb11_setup_fail;
  340. }
  341. return;
  342. usb11_setup_fail:
  343. gpio_free(DA850_USB1_OC_PIN);
  344. usb11_setup_oc_fail:
  345. gpio_free(DA850_USB1_VBUS_PIN);
  346. }
  347. static __init void omapl138_hawk_init(void)
  348. {
  349. int ret;
  350. da850_register_clocks();
  351. ret = da850_register_gpio();
  352. if (ret)
  353. pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
  354. davinci_serial_init(da8xx_serial_device);
  355. omapl138_hawk_config_emac();
  356. ret = da850_register_edma(da850_edma_rsv);
  357. if (ret)
  358. pr_warn("%s: EDMA registration failed: %d\n", __func__, ret);
  359. omapl138_hawk_mmc_init();
  360. omapl138_hawk_usb_init();
  361. ret = omapl138_hawk_register_aemif();
  362. if (ret)
  363. pr_warn("%s: aemif registration failed: %d\n", __func__, ret);
  364. ret = da8xx_register_watchdog();
  365. if (ret)
  366. pr_warn("%s: watchdog registration failed: %d\n",
  367. __func__, ret);
  368. ret = da8xx_register_rproc();
  369. if (ret)
  370. pr_warn("%s: dsp/rproc registration failed: %d\n",
  371. __func__, ret);
  372. regulator_has_full_constraints();
  373. }
  374. #ifdef CONFIG_SERIAL_8250_CONSOLE
  375. static int __init omapl138_hawk_console_init(void)
  376. {
  377. if (!machine_is_omapl138_hawkboard())
  378. return 0;
  379. return add_preferred_console("ttyS", 2, "115200");
  380. }
  381. console_initcall(omapl138_hawk_console_init);
  382. #endif
  383. static void __init omapl138_hawk_map_io(void)
  384. {
  385. da850_init();
  386. }
  387. MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
  388. .atag_offset = 0x100,
  389. .map_io = omapl138_hawk_map_io,
  390. .init_irq = cp_intc_init,
  391. .init_time = da850_init_time,
  392. .init_machine = omapl138_hawk_init,
  393. .init_late = davinci_init_late,
  394. .dma_zone_size = SZ_128M,
  395. .reserve = da8xx_rproc_reserve_cma,
  396. MACHINE_END