1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Freescale Lite5200 board support 4 * 5 * Written by: Grant Likely <grant.likely@secretlab.ca> 6 * 7 * Copyright (C) Secret Lab Technologies Ltd. 2006. All rights reserved. 8 * Copyright 2006 Freescale Semiconductor, Inc. All rights reserved. 9 * 10 * Description: 11 */ 12 13 #undef DEBUG 14 15 #include <linux/init.h> 16 #include <linux/pci.h> 17 #include <linux/of.h> 18 #include <linux/of_address.h> 19 #include <linux/root_dev.h> 20 #include <linux/initrd.h> 21 #include <asm/time.h> 22 #include <asm/io.h> 23 #include <asm/machdep.h> 24 #include <asm/prom.h> 25 #include <asm/mpc52xx.h> 26 27 /* ************************************************************************ 28 * 29 * Setup the architecture 30 * 31 */ 32 33 /* mpc5200 device tree match tables */ 34 static const struct of_device_id mpc5200_cdm_ids[] __initconst = { 35 { .compatible = "fsl,mpc5200-cdm", }, 36 { .compatible = "mpc5200-cdm", }, 37 {} 38 }; 39 40 static const struct of_device_id mpc5200_gpio_ids[] __initconst = { 41 { .compatible = "fsl,mpc5200-gpio", }, 42 { .compatible = "mpc5200-gpio", }, 43 {} 44 }; 45 46 /* 47 * Fix clock configuration. 48 * 49 * Firmware is supposed to be responsible for this. If you are creating a 50 * new board port, do *NOT* duplicate this code. Fix your boot firmware 51 * to set it correctly in the first place 52 */ 53 static void __init 54 lite5200_fix_clock_config(void) 55 { 56 struct device_node *np; 57 struct mpc52xx_cdm __iomem *cdm; 58 /* Map zones */ 59 np = of_find_matching_node(NULL, mpc5200_cdm_ids); 60 cdm = of_iomap(np, 0); 61 of_node_put(np); 62 if (!cdm) { 63 printk(KERN_ERR "%s() failed; expect abnormal behaviour\n", 64 __func__); 65 return; 66 } 67 68 /* Use internal 48 Mhz */ 69 out_8(&cdm->ext_48mhz_en, 0x00); 70 out_8(&cdm->fd_enable, 0x01); 71 if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ 72 out_be16(&cdm->fd_counters, 0x0001); 73 else 74 out_be16(&cdm->fd_counters, 0x5555); 75 76 /* Unmap the regs */ 77 iounmap(cdm); 78 } 79 80 /* 81 * Fix setting of port_config register. 82 * 83 * Firmware is supposed to be responsible for this. If you are creating a 84 * new board port, do *NOT* duplicate this code. Fix your boot firmware 85 * to set it correctly in the first place 86 */ 87 static void __init 88 lite5200_fix_port_config(void) 89 { 90 struct device_node *np; 91 struct mpc52xx_gpio __iomem *gpio; 92 u32 port_config; 93 94 np = of_find_matching_node(NULL, mpc5200_gpio_ids); 95 gpio = of_iomap(np, 0); 96 of_node_put(np); 97 if (!gpio) { 98 printk(KERN_ERR "%s() failed. expect abnormal behavior\n", 99 __func__); 100 return; 101 } 102 103 /* Set port config */ 104 port_config = in_be32(&gpio->port_config); 105 106 port_config &= ~0x00800000; /* 48Mhz internal, pin is GPIO */ 107 108 port_config &= ~0x00007000; /* USB port : Differential mode */ 109 port_config |= 0x00001000; /* USB 1 only */ 110 111 port_config &= ~0x03000000; /* ATA CS is on csb_4/5 */ 112 port_config |= 0x01000000; 113 114 pr_debug("port_config: old:%x new:%x\n", 115 in_be32(&gpio->port_config), port_config); 116 out_be32(&gpio->port_config, port_config); 117 118 /* Unmap zone */ 119 iounmap(gpio); 120 } 121 122 #ifdef CONFIG_PM 123 static void lite5200_suspend_prepare(void __iomem *mbar) 124 { 125 u8 pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */ 126 u8 level = 0; /* wakeup on low level */ 127 mpc52xx_set_wakeup_gpio(pin, level); 128 129 /* 130 * power down usb port 131 * this needs to be called before of-ohci suspend code 132 */ 133 134 /* set ports to "power switched" and "powered at the same time" 135 * USB Rh descriptor A: NPS = 0, PSM = 0 */ 136 out_be32(mbar + 0x1048, in_be32(mbar + 0x1048) & ~0x300); 137 /* USB Rh status: LPS = 1 - turn off power */ 138 out_be32(mbar + 0x1050, 0x00000001); 139 } 140 141 static void lite5200_resume_finish(void __iomem *mbar) 142 { 143 /* USB Rh status: LPSC = 1 - turn on power */ 144 out_be32(mbar + 0x1050, 0x00010000); 145 } 146 #endif 147 148 static void __init lite5200_setup_arch(void) 149 { 150 if (ppc_md.progress) 151 ppc_md.progress("lite5200_setup_arch()", 0); 152 153 /* Map important registers from the internal memory map */ 154 mpc52xx_map_common_devices(); 155 156 /* Some mpc5200 & mpc5200b related configuration */ 157 mpc5200_setup_xlb_arbiter(); 158 159 /* Fix things that firmware should have done. */ 160 lite5200_fix_clock_config(); 161 lite5200_fix_port_config(); 162 163 #ifdef CONFIG_PM 164 mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare; 165 mpc52xx_suspend.board_resume_finish = lite5200_resume_finish; 166 lite5200_pm_init(); 167 #endif 168 } 169 170 static const char * const board[] __initconst = { 171 "fsl,lite5200", 172 "fsl,lite5200b", 173 NULL, 174 }; 175 176 /* 177 * Called very early, MMU is off, device-tree isn't unflattened 178 */ 179 static int __init lite5200_probe(void) 180 { 181 return of_device_compatible_match(of_root, board); 182 } 183 184 define_machine(lite5200) { 185 .name = "lite5200", 186 .probe = lite5200_probe, 187 .setup_arch = lite5200_setup_arch, 188 .discover_phbs = mpc52xx_setup_pci, 189 .init = mpc52xx_declare_of_platform_devices, 190 .init_IRQ = mpc52xx_init_irq, 191 .get_irq = mpc52xx_get_irq, 192 .restart = mpc52xx_restart, 193 .calibrate_decr = generic_calibrate_decr, 194 }; 195