18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Freescale Lite5200 board support 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Written by: Grant Likely <grant.likely@secretlab.ca> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) Secret Lab Technologies Ltd. 2006. All rights reserved. 88c2ecf20Sopenharmony_ci * Copyright 2006 Freescale Semiconductor, Inc. All rights reserved. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Description: 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#undef DEBUG 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/init.h> 168c2ecf20Sopenharmony_ci#include <linux/pci.h> 178c2ecf20Sopenharmony_ci#include <linux/of.h> 188c2ecf20Sopenharmony_ci#include <linux/of_address.h> 198c2ecf20Sopenharmony_ci#include <linux/root_dev.h> 208c2ecf20Sopenharmony_ci#include <linux/initrd.h> 218c2ecf20Sopenharmony_ci#include <asm/time.h> 228c2ecf20Sopenharmony_ci#include <asm/io.h> 238c2ecf20Sopenharmony_ci#include <asm/machdep.h> 248c2ecf20Sopenharmony_ci#include <asm/prom.h> 258c2ecf20Sopenharmony_ci#include <asm/mpc52xx.h> 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* ************************************************************************ 288c2ecf20Sopenharmony_ci * 298c2ecf20Sopenharmony_ci * Setup the architecture 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/* mpc5200 device tree match tables */ 348c2ecf20Sopenharmony_cistatic const struct of_device_id mpc5200_cdm_ids[] __initconst = { 358c2ecf20Sopenharmony_ci { .compatible = "fsl,mpc5200-cdm", }, 368c2ecf20Sopenharmony_ci { .compatible = "mpc5200-cdm", }, 378c2ecf20Sopenharmony_ci {} 388c2ecf20Sopenharmony_ci}; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic const struct of_device_id mpc5200_gpio_ids[] __initconst = { 418c2ecf20Sopenharmony_ci { .compatible = "fsl,mpc5200-gpio", }, 428c2ecf20Sopenharmony_ci { .compatible = "mpc5200-gpio", }, 438c2ecf20Sopenharmony_ci {} 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* 478c2ecf20Sopenharmony_ci * Fix clock configuration. 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * Firmware is supposed to be responsible for this. If you are creating a 508c2ecf20Sopenharmony_ci * new board port, do *NOT* duplicate this code. Fix your boot firmware 518c2ecf20Sopenharmony_ci * to set it correctly in the first place 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_cistatic void __init 548c2ecf20Sopenharmony_cilite5200_fix_clock_config(void) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci struct device_node *np; 578c2ecf20Sopenharmony_ci struct mpc52xx_cdm __iomem *cdm; 588c2ecf20Sopenharmony_ci /* Map zones */ 598c2ecf20Sopenharmony_ci np = of_find_matching_node(NULL, mpc5200_cdm_ids); 608c2ecf20Sopenharmony_ci cdm = of_iomap(np, 0); 618c2ecf20Sopenharmony_ci of_node_put(np); 628c2ecf20Sopenharmony_ci if (!cdm) { 638c2ecf20Sopenharmony_ci printk(KERN_ERR "%s() failed; expect abnormal behaviour\n", 648c2ecf20Sopenharmony_ci __func__); 658c2ecf20Sopenharmony_ci return; 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci /* Use internal 48 Mhz */ 698c2ecf20Sopenharmony_ci out_8(&cdm->ext_48mhz_en, 0x00); 708c2ecf20Sopenharmony_ci out_8(&cdm->fd_enable, 0x01); 718c2ecf20Sopenharmony_ci if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ 728c2ecf20Sopenharmony_ci out_be16(&cdm->fd_counters, 0x0001); 738c2ecf20Sopenharmony_ci else 748c2ecf20Sopenharmony_ci out_be16(&cdm->fd_counters, 0x5555); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* Unmap the regs */ 778c2ecf20Sopenharmony_ci iounmap(cdm); 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci/* 818c2ecf20Sopenharmony_ci * Fix setting of port_config register. 828c2ecf20Sopenharmony_ci * 838c2ecf20Sopenharmony_ci * Firmware is supposed to be responsible for this. If you are creating a 848c2ecf20Sopenharmony_ci * new board port, do *NOT* duplicate this code. Fix your boot firmware 858c2ecf20Sopenharmony_ci * to set it correctly in the first place 868c2ecf20Sopenharmony_ci */ 878c2ecf20Sopenharmony_cistatic void __init 888c2ecf20Sopenharmony_cilite5200_fix_port_config(void) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci struct device_node *np; 918c2ecf20Sopenharmony_ci struct mpc52xx_gpio __iomem *gpio; 928c2ecf20Sopenharmony_ci u32 port_config; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci np = of_find_matching_node(NULL, mpc5200_gpio_ids); 958c2ecf20Sopenharmony_ci gpio = of_iomap(np, 0); 968c2ecf20Sopenharmony_ci of_node_put(np); 978c2ecf20Sopenharmony_ci if (!gpio) { 988c2ecf20Sopenharmony_ci printk(KERN_ERR "%s() failed. expect abnormal behavior\n", 998c2ecf20Sopenharmony_ci __func__); 1008c2ecf20Sopenharmony_ci return; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci /* Set port config */ 1048c2ecf20Sopenharmony_ci port_config = in_be32(&gpio->port_config); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci port_config &= ~0x00800000; /* 48Mhz internal, pin is GPIO */ 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci port_config &= ~0x00007000; /* USB port : Differential mode */ 1098c2ecf20Sopenharmony_ci port_config |= 0x00001000; /* USB 1 only */ 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci port_config &= ~0x03000000; /* ATA CS is on csb_4/5 */ 1128c2ecf20Sopenharmony_ci port_config |= 0x01000000; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci pr_debug("port_config: old:%x new:%x\n", 1158c2ecf20Sopenharmony_ci in_be32(&gpio->port_config), port_config); 1168c2ecf20Sopenharmony_ci out_be32(&gpio->port_config, port_config); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* Unmap zone */ 1198c2ecf20Sopenharmony_ci iounmap(gpio); 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 1238c2ecf20Sopenharmony_cistatic void lite5200_suspend_prepare(void __iomem *mbar) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci u8 pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */ 1268c2ecf20Sopenharmony_ci u8 level = 0; /* wakeup on low level */ 1278c2ecf20Sopenharmony_ci mpc52xx_set_wakeup_gpio(pin, level); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* 1308c2ecf20Sopenharmony_ci * power down usb port 1318c2ecf20Sopenharmony_ci * this needs to be called before of-ohci suspend code 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci /* set ports to "power switched" and "powered at the same time" 1358c2ecf20Sopenharmony_ci * USB Rh descriptor A: NPS = 0, PSM = 0 */ 1368c2ecf20Sopenharmony_ci out_be32(mbar + 0x1048, in_be32(mbar + 0x1048) & ~0x300); 1378c2ecf20Sopenharmony_ci /* USB Rh status: LPS = 1 - turn off power */ 1388c2ecf20Sopenharmony_ci out_be32(mbar + 0x1050, 0x00000001); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic void lite5200_resume_finish(void __iomem *mbar) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci /* USB Rh status: LPSC = 1 - turn on power */ 1448c2ecf20Sopenharmony_ci out_be32(mbar + 0x1050, 0x00010000); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci#endif 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic void __init lite5200_setup_arch(void) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci if (ppc_md.progress) 1518c2ecf20Sopenharmony_ci ppc_md.progress("lite5200_setup_arch()", 0); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* Map important registers from the internal memory map */ 1548c2ecf20Sopenharmony_ci mpc52xx_map_common_devices(); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci /* Some mpc5200 & mpc5200b related configuration */ 1578c2ecf20Sopenharmony_ci mpc5200_setup_xlb_arbiter(); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* Fix things that firmware should have done. */ 1608c2ecf20Sopenharmony_ci lite5200_fix_clock_config(); 1618c2ecf20Sopenharmony_ci lite5200_fix_port_config(); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 1648c2ecf20Sopenharmony_ci mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare; 1658c2ecf20Sopenharmony_ci mpc52xx_suspend.board_resume_finish = lite5200_resume_finish; 1668c2ecf20Sopenharmony_ci lite5200_pm_init(); 1678c2ecf20Sopenharmony_ci#endif 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci mpc52xx_setup_pci(); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic const char * const board[] __initconst = { 1738c2ecf20Sopenharmony_ci "fsl,lite5200", 1748c2ecf20Sopenharmony_ci "fsl,lite5200b", 1758c2ecf20Sopenharmony_ci NULL, 1768c2ecf20Sopenharmony_ci}; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci/* 1798c2ecf20Sopenharmony_ci * Called very early, MMU is off, device-tree isn't unflattened 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_cistatic int __init lite5200_probe(void) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci return of_device_compatible_match(of_root, board); 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cidefine_machine(lite5200) { 1878c2ecf20Sopenharmony_ci .name = "lite5200", 1888c2ecf20Sopenharmony_ci .probe = lite5200_probe, 1898c2ecf20Sopenharmony_ci .setup_arch = lite5200_setup_arch, 1908c2ecf20Sopenharmony_ci .init = mpc52xx_declare_of_platform_devices, 1918c2ecf20Sopenharmony_ci .init_IRQ = mpc52xx_init_irq, 1928c2ecf20Sopenharmony_ci .get_irq = mpc52xx_get_irq, 1938c2ecf20Sopenharmony_ci .restart = mpc52xx_restart, 1948c2ecf20Sopenharmony_ci .calibrate_decr = generic_calibrate_decr, 1958c2ecf20Sopenharmony_ci}; 196