Path: blob/master/arch/powerpc/platforms/85xx/mpc85xx_mds.c
10820 views
/*1* Copyright (C) Freescale Semicondutor, Inc. 2006-2010. All rights reserved.2*3* Author: Andy Fleming <[email protected]>4*5* Based on 83xx/mpc8360e_pb.c by:6* Li Yang <[email protected]>7* Yin Olivia <[email protected]>8*9* Description:10* MPC85xx MDS board specific routines.11*12* This program is free software; you can redistribute it and/or modify it13* under the terms of the GNU General Public License as published by the14* Free Software Foundation; either version 2 of the License, or (at your15* option) any later version.16*/1718#include <linux/stddef.h>19#include <linux/kernel.h>20#include <linux/init.h>21#include <linux/errno.h>22#include <linux/reboot.h>23#include <linux/pci.h>24#include <linux/kdev_t.h>25#include <linux/major.h>26#include <linux/console.h>27#include <linux/delay.h>28#include <linux/seq_file.h>29#include <linux/initrd.h>30#include <linux/module.h>31#include <linux/fsl_devices.h>32#include <linux/of_platform.h>33#include <linux/of_device.h>34#include <linux/phy.h>35#include <linux/memblock.h>3637#include <asm/system.h>38#include <asm/atomic.h>39#include <asm/time.h>40#include <asm/io.h>41#include <asm/machdep.h>42#include <asm/pci-bridge.h>43#include <asm/irq.h>44#include <mm/mmu_decl.h>45#include <asm/prom.h>46#include <asm/udbg.h>47#include <sysdev/fsl_soc.h>48#include <sysdev/fsl_pci.h>49#include <sysdev/simple_gpio.h>50#include <asm/qe.h>51#include <asm/qe_ic.h>52#include <asm/mpic.h>53#include <asm/swiotlb.h>5455#undef DEBUG56#ifdef DEBUG57#define DBG(fmt...) udbg_printf(fmt)58#else59#define DBG(fmt...)60#endif6162#define MV88E1111_SCR 0x1063#define MV88E1111_SCR_125CLK 0x001064static int mpc8568_fixup_125_clock(struct phy_device *phydev)65{66int scr;67int err;6869/* Workaround for the 125 CLK Toggle */70scr = phy_read(phydev, MV88E1111_SCR);7172if (scr < 0)73return scr;7475err = phy_write(phydev, MV88E1111_SCR, scr & ~(MV88E1111_SCR_125CLK));7677if (err)78return err;7980err = phy_write(phydev, MII_BMCR, BMCR_RESET);8182if (err)83return err;8485scr = phy_read(phydev, MV88E1111_SCR);8687if (scr < 0)88return scr;8990err = phy_write(phydev, MV88E1111_SCR, scr | 0x0008);9192return err;93}9495static int mpc8568_mds_phy_fixups(struct phy_device *phydev)96{97int temp;98int err;99100/* Errata */101err = phy_write(phydev,29, 0x0006);102103if (err)104return err;105106temp = phy_read(phydev, 30);107108if (temp < 0)109return temp;110111temp = (temp & (~0x8000)) | 0x4000;112err = phy_write(phydev,30, temp);113114if (err)115return err;116117err = phy_write(phydev,29, 0x000a);118119if (err)120return err;121122temp = phy_read(phydev, 30);123124if (temp < 0)125return temp;126127temp = phy_read(phydev, 30);128129if (temp < 0)130return temp;131132temp &= ~0x0020;133134err = phy_write(phydev,30,temp);135136if (err)137return err;138139/* Disable automatic MDI/MDIX selection */140temp = phy_read(phydev, 16);141142if (temp < 0)143return temp;144145temp &= ~0x0060;146err = phy_write(phydev,16,temp);147148return err;149}150151/* ************************************************************************152*153* Setup the architecture154*155*/156#ifdef CONFIG_SMP157extern void __init mpc85xx_smp_init(void);158#endif159160#ifdef CONFIG_QUICC_ENGINE161static struct of_device_id mpc85xx_qe_ids[] __initdata = {162{ .type = "qe", },163{ .compatible = "fsl,qe", },164{ },165};166167static void __init mpc85xx_publish_qe_devices(void)168{169struct device_node *np;170171np = of_find_compatible_node(NULL, NULL, "fsl,qe");172if (!of_device_is_available(np)) {173of_node_put(np);174return;175}176177of_platform_bus_probe(NULL, mpc85xx_qe_ids, NULL);178}179180static void __init mpc85xx_mds_reset_ucc_phys(void)181{182struct device_node *np;183static u8 __iomem *bcsr_regs;184185/* Map BCSR area */186np = of_find_node_by_name(NULL, "bcsr");187if (!np)188return;189190bcsr_regs = of_iomap(np, 0);191of_node_put(np);192if (!bcsr_regs)193return;194195if (machine_is(mpc8568_mds)) {196#define BCSR_UCC1_GETH_EN (0x1 << 7)197#define BCSR_UCC2_GETH_EN (0x1 << 7)198#define BCSR_UCC1_MODE_MSK (0x3 << 4)199#define BCSR_UCC2_MODE_MSK (0x3 << 0)200201/* Turn off UCC1 & UCC2 */202clrbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);203clrbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);204205/* Mode is RGMII, all bits clear */206clrbits8(&bcsr_regs[11], BCSR_UCC1_MODE_MSK |207BCSR_UCC2_MODE_MSK);208209/* Turn UCC1 & UCC2 on */210setbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);211setbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);212} else if (machine_is(mpc8569_mds)) {213#define BCSR7_UCC12_GETHnRST (0x1 << 2)214#define BCSR8_UEM_MARVELL_RST (0x1 << 1)215#define BCSR_UCC_RGMII (0x1 << 6)216#define BCSR_UCC_RTBI (0x1 << 5)217/*218* U-Boot mangles interrupt polarity for Marvell PHYs,219* so reset built-in and UEM Marvell PHYs, this puts220* the PHYs into their normal state.221*/222clrbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);223setbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);224225setbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);226clrbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);227228for (np = NULL; (np = of_find_compatible_node(np,229"network",230"ucc_geth")) != NULL;) {231const unsigned int *prop;232int ucc_num;233234prop = of_get_property(np, "cell-index", NULL);235if (prop == NULL)236continue;237238ucc_num = *prop - 1;239240prop = of_get_property(np, "phy-connection-type", NULL);241if (prop == NULL)242continue;243244if (strcmp("rtbi", (const char *)prop) == 0)245clrsetbits_8(&bcsr_regs[7 + ucc_num],246BCSR_UCC_RGMII, BCSR_UCC_RTBI);247}248} else if (machine_is(p1021_mds)) {249#define BCSR11_ENET_MICRST (0x1 << 5)250/* Reset Micrel PHY */251clrbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);252setbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);253}254255iounmap(bcsr_regs);256}257258static void __init mpc85xx_mds_qe_init(void)259{260struct device_node *np;261262np = of_find_compatible_node(NULL, NULL, "fsl,qe");263if (!np) {264np = of_find_node_by_name(NULL, "qe");265if (!np)266return;267}268269if (!of_device_is_available(np)) {270of_node_put(np);271return;272}273274qe_reset();275of_node_put(np);276277np = of_find_node_by_name(NULL, "par_io");278if (np) {279struct device_node *ucc;280281par_io_init(np);282of_node_put(np);283284for_each_node_by_name(ucc, "ucc")285par_io_of_config(ucc);286}287288mpc85xx_mds_reset_ucc_phys();289290if (machine_is(p1021_mds)) {291#define MPC85xx_PMUXCR_OFFSET 0x60292#define MPC85xx_PMUXCR_QE0 0x00008000293#define MPC85xx_PMUXCR_QE3 0x00001000294#define MPC85xx_PMUXCR_QE9 0x00000040295#define MPC85xx_PMUXCR_QE12 0x00000008296static __be32 __iomem *pmuxcr;297298np = of_find_node_by_name(NULL, "global-utilities");299300if (np) {301pmuxcr = of_iomap(np, 0) + MPC85xx_PMUXCR_OFFSET;302303if (!pmuxcr)304printk(KERN_EMERG "Error: Alternate function"305" signal multiplex control register not"306" mapped!\n");307else308/* P1021 has pins muxed for QE and other functions. To309* enable QE UEC mode, we need to set bit QE0 for UCC1310* in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9311* and QE12 for QE MII management signals in PMUXCR312* register.313*/314setbits32(pmuxcr, MPC85xx_PMUXCR_QE0 |315MPC85xx_PMUXCR_QE3 |316MPC85xx_PMUXCR_QE9 |317MPC85xx_PMUXCR_QE12);318319of_node_put(np);320}321322}323}324325static void __init mpc85xx_mds_qeic_init(void)326{327struct device_node *np;328329np = of_find_compatible_node(NULL, NULL, "fsl,qe");330if (!of_device_is_available(np)) {331of_node_put(np);332return;333}334335np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");336if (!np) {337np = of_find_node_by_type(NULL, "qeic");338if (!np)339return;340}341342if (machine_is(p1021_mds))343qe_ic_init(np, 0, qe_ic_cascade_low_mpic,344qe_ic_cascade_high_mpic);345else346qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL);347of_node_put(np);348}349#else350static void __init mpc85xx_publish_qe_devices(void) { }351static void __init mpc85xx_mds_qe_init(void) { }352static void __init mpc85xx_mds_qeic_init(void) { }353#endif /* CONFIG_QUICC_ENGINE */354355static void __init mpc85xx_mds_setup_arch(void)356{357#ifdef CONFIG_PCI358struct pci_controller *hose;359struct device_node *np;360#endif361dma_addr_t max = 0xffffffff;362363if (ppc_md.progress)364ppc_md.progress("mpc85xx_mds_setup_arch()", 0);365366#ifdef CONFIG_PCI367for_each_node_by_type(np, "pci") {368if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||369of_device_is_compatible(np, "fsl,mpc8548-pcie")) {370struct resource rsrc;371of_address_to_resource(np, 0, &rsrc);372if ((rsrc.start & 0xfffff) == 0x8000)373fsl_add_bridge(np, 1);374else375fsl_add_bridge(np, 0);376377hose = pci_find_hose_for_OF_device(np);378max = min(max, hose->dma_window_base_cur +379hose->dma_window_size);380}381}382#endif383384#ifdef CONFIG_SMP385mpc85xx_smp_init();386#endif387388mpc85xx_mds_qe_init();389390#ifdef CONFIG_SWIOTLB391if (memblock_end_of_DRAM() > max) {392ppc_swiotlb_enable = 1;393set_pci_dma_ops(&swiotlb_dma_ops);394ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;395}396#endif397}398399400static int __init board_fixups(void)401{402char phy_id[20];403char *compstrs[2] = {"fsl,gianfar-mdio", "fsl,ucc-mdio"};404struct device_node *mdio;405struct resource res;406int i;407408for (i = 0; i < ARRAY_SIZE(compstrs); i++) {409mdio = of_find_compatible_node(NULL, NULL, compstrs[i]);410411of_address_to_resource(mdio, 0, &res);412snprintf(phy_id, sizeof(phy_id), "%llx:%02x",413(unsigned long long)res.start, 1);414415phy_register_fixup_for_id(phy_id, mpc8568_fixup_125_clock);416phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups);417418/* Register a workaround for errata */419snprintf(phy_id, sizeof(phy_id), "%llx:%02x",420(unsigned long long)res.start, 7);421phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups);422423of_node_put(mdio);424}425426return 0;427}428machine_arch_initcall(mpc8568_mds, board_fixups);429machine_arch_initcall(mpc8569_mds, board_fixups);430431static struct of_device_id mpc85xx_ids[] = {432{ .type = "soc", },433{ .compatible = "soc", },434{ .compatible = "simple-bus", },435{ .compatible = "gianfar", },436{ .compatible = "fsl,rapidio-delta", },437{ .compatible = "fsl,mpc8548-guts", },438{ .compatible = "gpio-leds", },439{},440};441442static struct of_device_id p1021_ids[] = {443{ .type = "soc", },444{ .compatible = "soc", },445{ .compatible = "simple-bus", },446{ .compatible = "gianfar", },447{},448};449450static int __init mpc85xx_publish_devices(void)451{452if (machine_is(mpc8568_mds))453simple_gpiochip_init("fsl,mpc8568mds-bcsr-gpio");454if (machine_is(mpc8569_mds))455simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio");456457of_platform_bus_probe(NULL, mpc85xx_ids, NULL);458mpc85xx_publish_qe_devices();459460return 0;461}462463static int __init p1021_publish_devices(void)464{465of_platform_bus_probe(NULL, p1021_ids, NULL);466mpc85xx_publish_qe_devices();467468return 0;469}470471machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);472machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices);473machine_device_initcall(p1021_mds, p1021_publish_devices);474475machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier);476machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier);477machine_arch_initcall(p1021_mds, swiotlb_setup_bus_notifier);478479static void __init mpc85xx_mds_pic_init(void)480{481struct mpic *mpic;482struct resource r;483struct device_node *np = NULL;484485np = of_find_node_by_type(NULL, "open-pic");486if (!np)487return;488489if (of_address_to_resource(np, 0, &r)) {490printk(KERN_ERR "Failed to map mpic register space\n");491of_node_put(np);492return;493}494495mpic = mpic_alloc(np, r.start,496MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN |497MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,4980, 256, " OpenPIC ");499BUG_ON(mpic == NULL);500of_node_put(np);501502mpic_init(mpic);503mpc85xx_mds_qeic_init();504}505506static int __init mpc85xx_mds_probe(void)507{508unsigned long root = of_get_flat_dt_root();509510return of_flat_dt_is_compatible(root, "MPC85xxMDS");511}512513define_machine(mpc8568_mds) {514.name = "MPC8568 MDS",515.probe = mpc85xx_mds_probe,516.setup_arch = mpc85xx_mds_setup_arch,517.init_IRQ = mpc85xx_mds_pic_init,518.get_irq = mpic_get_irq,519.restart = fsl_rstcr_restart,520.calibrate_decr = generic_calibrate_decr,521.progress = udbg_progress,522#ifdef CONFIG_PCI523.pcibios_fixup_bus = fsl_pcibios_fixup_bus,524#endif525};526527static int __init mpc8569_mds_probe(void)528{529unsigned long root = of_get_flat_dt_root();530531return of_flat_dt_is_compatible(root, "fsl,MPC8569EMDS");532}533534define_machine(mpc8569_mds) {535.name = "MPC8569 MDS",536.probe = mpc8569_mds_probe,537.setup_arch = mpc85xx_mds_setup_arch,538.init_IRQ = mpc85xx_mds_pic_init,539.get_irq = mpic_get_irq,540.restart = fsl_rstcr_restart,541.calibrate_decr = generic_calibrate_decr,542.progress = udbg_progress,543#ifdef CONFIG_PCI544.pcibios_fixup_bus = fsl_pcibios_fixup_bus,545#endif546};547548static int __init p1021_mds_probe(void)549{550unsigned long root = of_get_flat_dt_root();551552return of_flat_dt_is_compatible(root, "fsl,P1021MDS");553554}555556define_machine(p1021_mds) {557.name = "P1021 MDS",558.probe = p1021_mds_probe,559.setup_arch = mpc85xx_mds_setup_arch,560.init_IRQ = mpc85xx_mds_pic_init,561.get_irq = mpic_get_irq,562.restart = fsl_rstcr_restart,563.calibrate_decr = generic_calibrate_decr,564.progress = udbg_progress,565#ifdef CONFIG_PCI566.pcibios_fixup_bus = fsl_pcibios_fixup_bus,567#endif568};569570571572