p1022_ds.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /*
  2. * P1022DS board specific routines
  3. *
  4. * Authors: Travis Wheatley <travis.wheatley@freescale.com>
  5. * Dave Liu <daveliu@freescale.com>
  6. * Timur Tabi <timur@freescale.com>
  7. *
  8. * Copyright 2010 Freescale Semiconductor, Inc.
  9. *
  10. * This file is taken from the Freescale P1022DS BSP, with modifications:
  11. * 2) No AMP support
  12. * 3) No PCI endpoint support
  13. *
  14. * This file is licensed under the terms of the GNU General Public License
  15. * version 2. This program is licensed "as is" without any warranty of any
  16. * kind, whether express or implied.
  17. */
  18. #include <linux/fsl/guts.h>
  19. #include <linux/pci.h>
  20. #include <linux/of_platform.h>
  21. #include <asm/div64.h>
  22. #include <asm/mpic.h>
  23. #include <asm/swiotlb.h>
  24. #include <sysdev/fsl_soc.h>
  25. #include <sysdev/fsl_pci.h>
  26. #include <asm/udbg.h>
  27. #include <asm/fsl_lbc.h>
  28. #include "smp.h"
  29. #include "mpc85xx.h"
  30. #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
  31. #define PMUXCR_ELBCDIU_MASK 0xc0000000
  32. #define PMUXCR_ELBCDIU_NOR16 0x80000000
  33. #define PMUXCR_ELBCDIU_DIU 0x40000000
  34. /*
  35. * Board-specific initialization of the DIU. This code should probably be
  36. * executed when the DIU is opened, rather than in arch code, but the DIU
  37. * driver does not have a mechanism for this (yet).
  38. *
  39. * This is especially problematic on the P1022DS because the local bus (eLBC)
  40. * and the DIU video signals share the same pins, which means that enabling the
  41. * DIU will disable access to NOR flash.
  42. */
  43. /* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
  44. #define CLKDVDR_PXCKEN 0x80000000
  45. #define CLKDVDR_PXCKINV 0x10000000
  46. #define CLKDVDR_PXCKDLY 0x06000000
  47. #define CLKDVDR_PXCLK_MASK 0x00FF0000
  48. /* Some ngPIXIS register definitions */
  49. #define PX_CTL 3
  50. #define PX_BRDCFG0 8
  51. #define PX_BRDCFG1 9
  52. #define PX_BRDCFG0_ELBC_SPI_MASK 0xc0
  53. #define PX_BRDCFG0_ELBC_SPI_ELBC 0x00
  54. #define PX_BRDCFG0_ELBC_SPI_NULL 0xc0
  55. #define PX_BRDCFG0_ELBC_DIU 0x02
  56. #define PX_BRDCFG1_DVIEN 0x80
  57. #define PX_BRDCFG1_DFPEN 0x40
  58. #define PX_BRDCFG1_BACKLIGHT 0x20
  59. #define PX_BRDCFG1_DDCEN 0x10
  60. #define PX_CTL_ALTACC 0x80
  61. /*
  62. * DIU Area Descriptor
  63. *
  64. * Note that we need to byte-swap the value before it's written to the AD
  65. * register. So even though the registers don't look like they're in the same
  66. * bit positions as they are on the MPC8610, the same value is written to the
  67. * AD register on the MPC8610 and on the P1022.
  68. */
  69. #define AD_BYTE_F 0x10000000
  70. #define AD_ALPHA_C_MASK 0x0E000000
  71. #define AD_ALPHA_C_SHIFT 25
  72. #define AD_BLUE_C_MASK 0x01800000
  73. #define AD_BLUE_C_SHIFT 23
  74. #define AD_GREEN_C_MASK 0x00600000
  75. #define AD_GREEN_C_SHIFT 21
  76. #define AD_RED_C_MASK 0x00180000
  77. #define AD_RED_C_SHIFT 19
  78. #define AD_PALETTE 0x00040000
  79. #define AD_PIXEL_S_MASK 0x00030000
  80. #define AD_PIXEL_S_SHIFT 16
  81. #define AD_COMP_3_MASK 0x0000F000
  82. #define AD_COMP_3_SHIFT 12
  83. #define AD_COMP_2_MASK 0x00000F00
  84. #define AD_COMP_2_SHIFT 8
  85. #define AD_COMP_1_MASK 0x000000F0
  86. #define AD_COMP_1_SHIFT 4
  87. #define AD_COMP_0_MASK 0x0000000F
  88. #define AD_COMP_0_SHIFT 0
  89. #define MAKE_AD(alpha, red, blue, green, size, c0, c1, c2, c3) \
  90. cpu_to_le32(AD_BYTE_F | (alpha << AD_ALPHA_C_SHIFT) | \
  91. (blue << AD_BLUE_C_SHIFT) | (green << AD_GREEN_C_SHIFT) | \
  92. (red << AD_RED_C_SHIFT) | (c3 << AD_COMP_3_SHIFT) | \
  93. (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
  94. (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
  95. struct fsl_law {
  96. u32 lawbar;
  97. u32 reserved1;
  98. u32 lawar;
  99. u32 reserved[5];
  100. };
  101. #define LAWBAR_MASK 0x00F00000
  102. #define LAWBAR_SHIFT 12
  103. #define LAWAR_EN 0x80000000
  104. #define LAWAR_TGT_MASK 0x01F00000
  105. #define LAW_TRGT_IF_LBC (0x04 << 20)
  106. #define LAWAR_MASK (LAWAR_EN | LAWAR_TGT_MASK)
  107. #define LAWAR_MATCH (LAWAR_EN | LAW_TRGT_IF_LBC)
  108. #define BR_BA 0xFFFF8000
  109. /*
  110. * Map a BRx value to a physical address
  111. *
  112. * The localbus BRx registers only store the lower 32 bits of the address. To
  113. * obtain the upper four bits, we need to scan the LAW table. The entry which
  114. * maps to the localbus will contain the upper four bits.
  115. */
  116. static phys_addr_t lbc_br_to_phys(const void *ecm, unsigned int count, u32 br)
  117. {
  118. #ifndef CONFIG_PHYS_64BIT
  119. /*
  120. * If we only have 32-bit addressing, then the BRx address *is* the
  121. * physical address.
  122. */
  123. return br & BR_BA;
  124. #else
  125. const struct fsl_law *law = ecm + 0xc08;
  126. unsigned int i;
  127. for (i = 0; i < count; i++) {
  128. u64 lawbar = in_be32(&law[i].lawbar);
  129. u32 lawar = in_be32(&law[i].lawar);
  130. if ((lawar & LAWAR_MASK) == LAWAR_MATCH)
  131. /* Extract the upper four bits */
  132. return (br & BR_BA) | ((lawbar & LAWBAR_MASK) << 12);
  133. }
  134. return 0;
  135. #endif
  136. }
  137. /**
  138. * p1022ds_set_monitor_port: switch the output to a different monitor port
  139. */
  140. static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
  141. {
  142. struct device_node *guts_node;
  143. struct device_node *lbc_node = NULL;
  144. struct device_node *law_node = NULL;
  145. struct ccsr_guts __iomem *guts;
  146. struct fsl_lbc_regs *lbc = NULL;
  147. void *ecm = NULL;
  148. u8 __iomem *lbc_lcs0_ba = NULL;
  149. u8 __iomem *lbc_lcs1_ba = NULL;
  150. phys_addr_t cs0_addr, cs1_addr;
  151. u32 br0, or0, br1, or1;
  152. const __be32 *iprop;
  153. unsigned int num_laws;
  154. u8 b;
  155. /* Map the global utilities registers. */
  156. guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
  157. if (!guts_node) {
  158. pr_err("p1022ds: missing global utilities device node\n");
  159. return;
  160. }
  161. guts = of_iomap(guts_node, 0);
  162. if (!guts) {
  163. pr_err("p1022ds: could not map global utilities device\n");
  164. goto exit;
  165. }
  166. lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc");
  167. if (!lbc_node) {
  168. pr_err("p1022ds: missing localbus node\n");
  169. goto exit;
  170. }
  171. lbc = of_iomap(lbc_node, 0);
  172. if (!lbc) {
  173. pr_err("p1022ds: could not map localbus node\n");
  174. goto exit;
  175. }
  176. law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law");
  177. if (!law_node) {
  178. pr_err("p1022ds: missing local access window node\n");
  179. goto exit;
  180. }
  181. ecm = of_iomap(law_node, 0);
  182. if (!ecm) {
  183. pr_err("p1022ds: could not map local access window node\n");
  184. goto exit;
  185. }
  186. iprop = of_get_property(law_node, "fsl,num-laws", NULL);
  187. if (!iprop) {
  188. pr_err("p1022ds: LAW node is missing fsl,num-laws property\n");
  189. goto exit;
  190. }
  191. num_laws = be32_to_cpup(iprop);
  192. /*
  193. * Indirect mode requires both BR0 and BR1 to be set to "GPCM",
  194. * otherwise writes to these addresses won't actually appear on the
  195. * local bus, and so the PIXIS won't see them.
  196. *
  197. * In FCM mode, writes go to the NAND controller, which does not pass
  198. * them to the localbus directly. So we force BR0 and BR1 into GPCM
  199. * mode, since we don't care about what's behind the localbus any
  200. * more.
  201. */
  202. br0 = in_be32(&lbc->bank[0].br);
  203. br1 = in_be32(&lbc->bank[1].br);
  204. or0 = in_be32(&lbc->bank[0].or);
  205. or1 = in_be32(&lbc->bank[1].or);
  206. /* Make sure CS0 and CS1 are programmed */
  207. if (!(br0 & BR_V) || !(br1 & BR_V)) {
  208. pr_err("p1022ds: CS0 and/or CS1 is not programmed\n");
  209. goto exit;
  210. }
  211. /*
  212. * Use the existing BRx/ORx values if it's already GPCM. Otherwise,
  213. * force the values to simple 32KB GPCM windows with the most
  214. * conservative timing.
  215. */
  216. if ((br0 & BR_MSEL) != BR_MS_GPCM) {
  217. br0 = (br0 & BR_BA) | BR_V;
  218. or0 = 0xFFFF8000 | 0xFF7;
  219. out_be32(&lbc->bank[0].br, br0);
  220. out_be32(&lbc->bank[0].or, or0);
  221. }
  222. if ((br1 & BR_MSEL) != BR_MS_GPCM) {
  223. br1 = (br1 & BR_BA) | BR_V;
  224. or1 = 0xFFFF8000 | 0xFF7;
  225. out_be32(&lbc->bank[1].br, br1);
  226. out_be32(&lbc->bank[1].or, or1);
  227. }
  228. cs0_addr = lbc_br_to_phys(ecm, num_laws, br0);
  229. if (!cs0_addr) {
  230. pr_err("p1022ds: could not determine physical address for CS0"
  231. " (BR0=%08x)\n", br0);
  232. goto exit;
  233. }
  234. cs1_addr = lbc_br_to_phys(ecm, num_laws, br1);
  235. if (!cs1_addr) {
  236. pr_err("p1022ds: could not determine physical address for CS1"
  237. " (BR1=%08x)\n", br1);
  238. goto exit;
  239. }
  240. lbc_lcs0_ba = ioremap(cs0_addr, 1);
  241. if (!lbc_lcs0_ba) {
  242. pr_err("p1022ds: could not ioremap CS0 address %llx\n",
  243. (unsigned long long)cs0_addr);
  244. goto exit;
  245. }
  246. lbc_lcs1_ba = ioremap(cs1_addr, 1);
  247. if (!lbc_lcs1_ba) {
  248. pr_err("p1022ds: could not ioremap CS1 address %llx\n",
  249. (unsigned long long)cs1_addr);
  250. goto exit;
  251. }
  252. /* Make sure we're in indirect mode first. */
  253. if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) !=
  254. PMUXCR_ELBCDIU_DIU) {
  255. struct device_node *pixis_node;
  256. void __iomem *pixis;
  257. pixis_node =
  258. of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga");
  259. if (!pixis_node) {
  260. pr_err("p1022ds: missing pixis node\n");
  261. goto exit;
  262. }
  263. pixis = of_iomap(pixis_node, 0);
  264. of_node_put(pixis_node);
  265. if (!pixis) {
  266. pr_err("p1022ds: could not map pixis registers\n");
  267. goto exit;
  268. }
  269. /* Enable indirect PIXIS mode. */
  270. setbits8(pixis + PX_CTL, PX_CTL_ALTACC);
  271. iounmap(pixis);
  272. /* Switch the board mux to the DIU */
  273. out_8(lbc_lcs0_ba, PX_BRDCFG0); /* BRDCFG0 */
  274. b = in_8(lbc_lcs1_ba);
  275. b |= PX_BRDCFG0_ELBC_DIU;
  276. out_8(lbc_lcs1_ba, b);
  277. /* Set the chip mux to DIU mode. */
  278. clrsetbits_be32(&guts->pmuxcr, PMUXCR_ELBCDIU_MASK,
  279. PMUXCR_ELBCDIU_DIU);
  280. in_be32(&guts->pmuxcr);
  281. }
  282. switch (port) {
  283. case FSL_DIU_PORT_DVI:
  284. /* Enable the DVI port, disable the DFP and the backlight */
  285. out_8(lbc_lcs0_ba, PX_BRDCFG1);
  286. b = in_8(lbc_lcs1_ba);
  287. b &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT);
  288. b |= PX_BRDCFG1_DVIEN;
  289. out_8(lbc_lcs1_ba, b);
  290. break;
  291. case FSL_DIU_PORT_LVDS:
  292. /*
  293. * LVDS also needs backlight enabled, otherwise the display
  294. * will be blank.
  295. */
  296. /* Enable the DFP port, disable the DVI and the backlight */
  297. out_8(lbc_lcs0_ba, PX_BRDCFG1);
  298. b = in_8(lbc_lcs1_ba);
  299. b &= ~PX_BRDCFG1_DVIEN;
  300. b |= PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT;
  301. out_8(lbc_lcs1_ba, b);
  302. break;
  303. default:
  304. pr_err("p1022ds: unsupported monitor port %i\n", port);
  305. }
  306. exit:
  307. if (lbc_lcs1_ba)
  308. iounmap(lbc_lcs1_ba);
  309. if (lbc_lcs0_ba)
  310. iounmap(lbc_lcs0_ba);
  311. if (lbc)
  312. iounmap(lbc);
  313. if (ecm)
  314. iounmap(ecm);
  315. if (guts)
  316. iounmap(guts);
  317. of_node_put(law_node);
  318. of_node_put(lbc_node);
  319. of_node_put(guts_node);
  320. }
  321. /**
  322. * p1022ds_set_pixel_clock: program the DIU's clock
  323. *
  324. * @pixclock: the wavelength, in picoseconds, of the clock
  325. */
  326. void p1022ds_set_pixel_clock(unsigned int pixclock)
  327. {
  328. struct device_node *guts_np = NULL;
  329. struct ccsr_guts __iomem *guts;
  330. unsigned long freq;
  331. u64 temp;
  332. u32 pxclk;
  333. /* Map the global utilities registers. */
  334. guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
  335. if (!guts_np) {
  336. pr_err("p1022ds: missing global utilities device node\n");
  337. return;
  338. }
  339. guts = of_iomap(guts_np, 0);
  340. of_node_put(guts_np);
  341. if (!guts) {
  342. pr_err("p1022ds: could not map global utilities device\n");
  343. return;
  344. }
  345. /* Convert pixclock from a wavelength to a frequency */
  346. temp = 1000000000000ULL;
  347. do_div(temp, pixclock);
  348. freq = temp;
  349. /*
  350. * 'pxclk' is the ratio of the platform clock to the pixel clock.
  351. * This number is programmed into the CLKDVDR register, and the valid
  352. * range of values is 2-255.
  353. */
  354. pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
  355. pxclk = clamp_t(u32, pxclk, 2, 255);
  356. /* Disable the pixel clock, and set it to non-inverted and no delay */
  357. clrbits32(&guts->clkdvdr,
  358. CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
  359. /* Enable the clock and set the pxclk */
  360. setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
  361. iounmap(guts);
  362. }
  363. /**
  364. * p1022ds_valid_monitor_port: set the monitor port for sysfs
  365. */
  366. enum fsl_diu_monitor_port
  367. p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)
  368. {
  369. switch (port) {
  370. case FSL_DIU_PORT_DVI:
  371. case FSL_DIU_PORT_LVDS:
  372. return port;
  373. default:
  374. return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */
  375. }
  376. }
  377. #endif
  378. void __init p1022_ds_pic_init(void)
  379. {
  380. struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
  381. MPIC_SINGLE_DEST_CPU,
  382. 0, 256, " OpenPIC ");
  383. BUG_ON(mpic == NULL);
  384. mpic_init(mpic);
  385. }
  386. #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
  387. /* TRUE if there is a "video=fslfb" command-line parameter. */
  388. static bool fslfb;
  389. /*
  390. * Search for a "video=fslfb" command-line parameter, and set 'fslfb' to
  391. * true if we find it.
  392. *
  393. * We need to use early_param() instead of __setup() because the normal
  394. * __setup() gets called to late. However, early_param() gets called very
  395. * early, before the device tree is unflattened, so all we can do now is set a
  396. * global variable. Later on, p1022_ds_setup_arch() will use that variable
  397. * to determine if we need to update the device tree.
  398. */
  399. static int __init early_video_setup(char *options)
  400. {
  401. fslfb = (strncmp(options, "fslfb:", 6) == 0);
  402. return 0;
  403. }
  404. early_param("video", early_video_setup);
  405. #endif
  406. /*
  407. * Setup the architecture
  408. */
  409. static void __init p1022_ds_setup_arch(void)
  410. {
  411. if (ppc_md.progress)
  412. ppc_md.progress("p1022_ds_setup_arch()", 0);
  413. #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
  414. diu_ops.set_monitor_port = p1022ds_set_monitor_port;
  415. diu_ops.set_pixel_clock = p1022ds_set_pixel_clock;
  416. diu_ops.valid_monitor_port = p1022ds_valid_monitor_port;
  417. /*
  418. * Disable the NOR and NAND flash nodes if there is video=fslfb...
  419. * command-line parameter. When the DIU is active, the localbus is
  420. * unavailable, so we have to disable these nodes before the MTD
  421. * driver loads.
  422. */
  423. if (fslfb) {
  424. struct device_node *np =
  425. of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc");
  426. if (np) {
  427. struct device_node *np2;
  428. of_node_get(np);
  429. np2 = of_find_compatible_node(np, NULL, "cfi-flash");
  430. if (np2) {
  431. static struct property nor_status = {
  432. .name = "status",
  433. .value = "disabled",
  434. .length = sizeof("disabled"),
  435. };
  436. /*
  437. * of_update_property() is called before
  438. * kmalloc() is available, so the 'new' object
  439. * should be allocated in the global area.
  440. * The easiest way is to do that is to
  441. * allocate one static local variable for each
  442. * call to this function.
  443. */
  444. pr_info("p1022ds: disabling %s node",
  445. np2->full_name);
  446. of_update_property(np2, &nor_status);
  447. of_node_put(np2);
  448. }
  449. of_node_get(np);
  450. np2 = of_find_compatible_node(np, NULL,
  451. "fsl,elbc-fcm-nand");
  452. if (np2) {
  453. static struct property nand_status = {
  454. .name = "status",
  455. .value = "disabled",
  456. .length = sizeof("disabled"),
  457. };
  458. pr_info("p1022ds: disabling %s node",
  459. np2->full_name);
  460. of_update_property(np2, &nand_status);
  461. of_node_put(np2);
  462. }
  463. of_node_put(np);
  464. }
  465. }
  466. #endif
  467. mpc85xx_smp_init();
  468. fsl_pci_assign_primary();
  469. swiotlb_detect_4g();
  470. pr_info("Freescale P1022 DS reference board\n");
  471. }
  472. machine_arch_initcall(p1022_ds, mpc85xx_common_publish_devices);
  473. machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier);
  474. /*
  475. * Called very early, device-tree isn't unflattened
  476. */
  477. static int __init p1022_ds_probe(void)
  478. {
  479. unsigned long root = of_get_flat_dt_root();
  480. return of_flat_dt_is_compatible(root, "fsl,p1022ds");
  481. }
  482. define_machine(p1022_ds) {
  483. .name = "P1022 DS",
  484. .probe = p1022_ds_probe,
  485. .setup_arch = p1022_ds_setup_arch,
  486. .init_IRQ = p1022_ds_pic_init,
  487. #ifdef CONFIG_PCI
  488. .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
  489. .pcibios_fixup_phb = fsl_pcibios_fixup_phb,
  490. #endif
  491. .get_irq = mpic_get_irq,
  492. .restart = fsl_rstcr_restart,
  493. .calibrate_decr = generic_calibrate_decr,
  494. .progress = udbg_progress,
  495. };