162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Freescale Lite5200 board support 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Written by: Grant Likely <grant.likely@secretlab.ca> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) Secret Lab Technologies Ltd. 2006. All rights reserved. 862306a36Sopenharmony_ci * Copyright 2006 Freescale Semiconductor, Inc. All rights reserved. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Description: 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#undef DEBUG 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/init.h> 1662306a36Sopenharmony_ci#include <linux/pci.h> 1762306a36Sopenharmony_ci#include <linux/of.h> 1862306a36Sopenharmony_ci#include <linux/of_address.h> 1962306a36Sopenharmony_ci#include <linux/root_dev.h> 2062306a36Sopenharmony_ci#include <linux/initrd.h> 2162306a36Sopenharmony_ci#include <asm/time.h> 2262306a36Sopenharmony_ci#include <asm/io.h> 2362306a36Sopenharmony_ci#include <asm/machdep.h> 2462306a36Sopenharmony_ci#include <asm/mpc52xx.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* ************************************************************************ 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * Setup the architecture 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* mpc5200 device tree match tables */ 3362306a36Sopenharmony_cistatic const struct of_device_id mpc5200_cdm_ids[] __initconst = { 3462306a36Sopenharmony_ci { .compatible = "fsl,mpc5200-cdm", }, 3562306a36Sopenharmony_ci { .compatible = "mpc5200-cdm", }, 3662306a36Sopenharmony_ci {} 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic const struct of_device_id mpc5200_gpio_ids[] __initconst = { 4062306a36Sopenharmony_ci { .compatible = "fsl,mpc5200-gpio", }, 4162306a36Sopenharmony_ci { .compatible = "mpc5200-gpio", }, 4262306a36Sopenharmony_ci {} 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* 4662306a36Sopenharmony_ci * Fix clock configuration. 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * Firmware is supposed to be responsible for this. If you are creating a 4962306a36Sopenharmony_ci * new board port, do *NOT* duplicate this code. Fix your boot firmware 5062306a36Sopenharmony_ci * to set it correctly in the first place 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_cistatic void __init 5362306a36Sopenharmony_cilite5200_fix_clock_config(void) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci struct device_node *np; 5662306a36Sopenharmony_ci struct mpc52xx_cdm __iomem *cdm; 5762306a36Sopenharmony_ci /* Map zones */ 5862306a36Sopenharmony_ci np = of_find_matching_node(NULL, mpc5200_cdm_ids); 5962306a36Sopenharmony_ci cdm = of_iomap(np, 0); 6062306a36Sopenharmony_ci of_node_put(np); 6162306a36Sopenharmony_ci if (!cdm) { 6262306a36Sopenharmony_ci printk(KERN_ERR "%s() failed; expect abnormal behaviour\n", 6362306a36Sopenharmony_ci __func__); 6462306a36Sopenharmony_ci return; 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* Use internal 48 Mhz */ 6862306a36Sopenharmony_ci out_8(&cdm->ext_48mhz_en, 0x00); 6962306a36Sopenharmony_ci out_8(&cdm->fd_enable, 0x01); 7062306a36Sopenharmony_ci if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ 7162306a36Sopenharmony_ci out_be16(&cdm->fd_counters, 0x0001); 7262306a36Sopenharmony_ci else 7362306a36Sopenharmony_ci out_be16(&cdm->fd_counters, 0x5555); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci /* Unmap the regs */ 7662306a36Sopenharmony_ci iounmap(cdm); 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* 8062306a36Sopenharmony_ci * Fix setting of port_config register. 8162306a36Sopenharmony_ci * 8262306a36Sopenharmony_ci * Firmware is supposed to be responsible for this. If you are creating a 8362306a36Sopenharmony_ci * new board port, do *NOT* duplicate this code. Fix your boot firmware 8462306a36Sopenharmony_ci * to set it correctly in the first place 8562306a36Sopenharmony_ci */ 8662306a36Sopenharmony_cistatic void __init 8762306a36Sopenharmony_cilite5200_fix_port_config(void) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci struct device_node *np; 9062306a36Sopenharmony_ci struct mpc52xx_gpio __iomem *gpio; 9162306a36Sopenharmony_ci u32 port_config; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci np = of_find_matching_node(NULL, mpc5200_gpio_ids); 9462306a36Sopenharmony_ci gpio = of_iomap(np, 0); 9562306a36Sopenharmony_ci of_node_put(np); 9662306a36Sopenharmony_ci if (!gpio) { 9762306a36Sopenharmony_ci printk(KERN_ERR "%s() failed. expect abnormal behavior\n", 9862306a36Sopenharmony_ci __func__); 9962306a36Sopenharmony_ci return; 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci /* Set port config */ 10362306a36Sopenharmony_ci port_config = in_be32(&gpio->port_config); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci port_config &= ~0x00800000; /* 48Mhz internal, pin is GPIO */ 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci port_config &= ~0x00007000; /* USB port : Differential mode */ 10862306a36Sopenharmony_ci port_config |= 0x00001000; /* USB 1 only */ 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci port_config &= ~0x03000000; /* ATA CS is on csb_4/5 */ 11162306a36Sopenharmony_ci port_config |= 0x01000000; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci pr_debug("port_config: old:%x new:%x\n", 11462306a36Sopenharmony_ci in_be32(&gpio->port_config), port_config); 11562306a36Sopenharmony_ci out_be32(&gpio->port_config, port_config); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* Unmap zone */ 11862306a36Sopenharmony_ci iounmap(gpio); 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#ifdef CONFIG_PM 12262306a36Sopenharmony_cistatic void lite5200_suspend_prepare(void __iomem *mbar) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci u8 pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */ 12562306a36Sopenharmony_ci u8 level = 0; /* wakeup on low level */ 12662306a36Sopenharmony_ci mpc52xx_set_wakeup_gpio(pin, level); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* 12962306a36Sopenharmony_ci * power down usb port 13062306a36Sopenharmony_ci * this needs to be called before of-ohci suspend code 13162306a36Sopenharmony_ci */ 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* set ports to "power switched" and "powered at the same time" 13462306a36Sopenharmony_ci * USB Rh descriptor A: NPS = 0, PSM = 0 */ 13562306a36Sopenharmony_ci out_be32(mbar + 0x1048, in_be32(mbar + 0x1048) & ~0x300); 13662306a36Sopenharmony_ci /* USB Rh status: LPS = 1 - turn off power */ 13762306a36Sopenharmony_ci out_be32(mbar + 0x1050, 0x00000001); 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic void lite5200_resume_finish(void __iomem *mbar) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci /* USB Rh status: LPSC = 1 - turn on power */ 14362306a36Sopenharmony_ci out_be32(mbar + 0x1050, 0x00010000); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci#endif 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic void __init lite5200_setup_arch(void) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci if (ppc_md.progress) 15062306a36Sopenharmony_ci ppc_md.progress("lite5200_setup_arch()", 0); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci /* Map important registers from the internal memory map */ 15362306a36Sopenharmony_ci mpc52xx_map_common_devices(); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci /* Some mpc5200 & mpc5200b related configuration */ 15662306a36Sopenharmony_ci mpc5200_setup_xlb_arbiter(); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* Fix things that firmware should have done. */ 15962306a36Sopenharmony_ci lite5200_fix_clock_config(); 16062306a36Sopenharmony_ci lite5200_fix_port_config(); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci#ifdef CONFIG_PM 16362306a36Sopenharmony_ci mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare; 16462306a36Sopenharmony_ci mpc52xx_suspend.board_resume_finish = lite5200_resume_finish; 16562306a36Sopenharmony_ci lite5200_pm_init(); 16662306a36Sopenharmony_ci#endif 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic const char * const board[] __initconst = { 17062306a36Sopenharmony_ci "fsl,lite5200", 17162306a36Sopenharmony_ci "fsl,lite5200b", 17262306a36Sopenharmony_ci NULL, 17362306a36Sopenharmony_ci}; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/* 17662306a36Sopenharmony_ci * Called very early, MMU is off, device-tree isn't unflattened 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_cistatic int __init lite5200_probe(void) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci return of_device_compatible_match(of_root, board); 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cidefine_machine(lite5200) { 18462306a36Sopenharmony_ci .name = "lite5200", 18562306a36Sopenharmony_ci .probe = lite5200_probe, 18662306a36Sopenharmony_ci .setup_arch = lite5200_setup_arch, 18762306a36Sopenharmony_ci .discover_phbs = mpc52xx_setup_pci, 18862306a36Sopenharmony_ci .init = mpc52xx_declare_of_platform_devices, 18962306a36Sopenharmony_ci .init_IRQ = mpc52xx_init_irq, 19062306a36Sopenharmony_ci .get_irq = mpc52xx_get_irq, 19162306a36Sopenharmony_ci .restart = mpc52xx_restart, 19262306a36Sopenharmony_ci}; 193