Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Embedded Planet EP8248E support
0004  *
0005  * Copyright 2007 Freescale Semiconductor, Inc.
0006  * Author: Scott Wood <scottwood@freescale.com>
0007  */
0008 
0009 #include <linux/init.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/fsl_devices.h>
0012 #include <linux/mdio-bitbang.h>
0013 #include <linux/of_mdio.h>
0014 #include <linux/slab.h>
0015 #include <linux/of_platform.h>
0016 
0017 #include <asm/io.h>
0018 #include <asm/cpm2.h>
0019 #include <asm/udbg.h>
0020 #include <asm/machdep.h>
0021 #include <asm/time.h>
0022 #include <asm/mpc8260.h>
0023 
0024 #include <sysdev/fsl_soc.h>
0025 #include <sysdev/cpm2_pic.h>
0026 
0027 #include "pq2.h"
0028 
0029 static u8 __iomem *ep8248e_bcsr;
0030 static struct device_node *ep8248e_bcsr_node;
0031 
0032 #define BCSR7_SCC2_ENABLE 0x10
0033 
0034 #define BCSR8_PHY1_ENABLE 0x80
0035 #define BCSR8_PHY1_POWER  0x40
0036 #define BCSR8_PHY2_ENABLE 0x20
0037 #define BCSR8_PHY2_POWER  0x10
0038 #define BCSR8_MDIO_READ   0x04
0039 #define BCSR8_MDIO_CLOCK  0x02
0040 #define BCSR8_MDIO_DATA   0x01
0041 
0042 #define BCSR9_USB_ENABLE  0x80
0043 #define BCSR9_USB_POWER   0x40
0044 #define BCSR9_USB_HOST    0x20
0045 #define BCSR9_USB_FULL_SPEED_TARGET 0x10
0046 
0047 static void __init ep8248e_pic_init(void)
0048 {
0049     struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,pq2-pic");
0050     if (!np) {
0051         printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
0052         return;
0053     }
0054 
0055     cpm2_pic_init(np);
0056     of_node_put(np);
0057 }
0058 
0059 static void ep8248e_set_mdc(struct mdiobb_ctrl *ctrl, int level)
0060 {
0061     if (level)
0062         setbits8(&ep8248e_bcsr[8], BCSR8_MDIO_CLOCK);
0063     else
0064         clrbits8(&ep8248e_bcsr[8], BCSR8_MDIO_CLOCK);
0065 
0066     /* Read back to flush the write. */
0067     in_8(&ep8248e_bcsr[8]);
0068 }
0069 
0070 static void ep8248e_set_mdio_dir(struct mdiobb_ctrl *ctrl, int output)
0071 {
0072     if (output)
0073         clrbits8(&ep8248e_bcsr[8], BCSR8_MDIO_READ);
0074     else
0075         setbits8(&ep8248e_bcsr[8], BCSR8_MDIO_READ);
0076 
0077     /* Read back to flush the write. */
0078     in_8(&ep8248e_bcsr[8]);
0079 }
0080 
0081 static void ep8248e_set_mdio_data(struct mdiobb_ctrl *ctrl, int data)
0082 {
0083     if (data)
0084         setbits8(&ep8248e_bcsr[8], BCSR8_MDIO_DATA);
0085     else
0086         clrbits8(&ep8248e_bcsr[8], BCSR8_MDIO_DATA);
0087 
0088     /* Read back to flush the write. */
0089     in_8(&ep8248e_bcsr[8]);
0090 }
0091 
0092 static int ep8248e_get_mdio_data(struct mdiobb_ctrl *ctrl)
0093 {
0094     return in_8(&ep8248e_bcsr[8]) & BCSR8_MDIO_DATA;
0095 }
0096 
0097 static const struct mdiobb_ops ep8248e_mdio_ops = {
0098     .set_mdc = ep8248e_set_mdc,
0099     .set_mdio_dir = ep8248e_set_mdio_dir,
0100     .set_mdio_data = ep8248e_set_mdio_data,
0101     .get_mdio_data = ep8248e_get_mdio_data,
0102     .owner = THIS_MODULE,
0103 };
0104 
0105 static struct mdiobb_ctrl ep8248e_mdio_ctrl = {
0106     .ops = &ep8248e_mdio_ops,
0107 };
0108 
0109 static int ep8248e_mdio_probe(struct platform_device *ofdev)
0110 {
0111     struct mii_bus *bus;
0112     struct resource res;
0113     struct device_node *node;
0114     int ret;
0115 
0116     node = of_get_parent(ofdev->dev.of_node);
0117     of_node_put(node);
0118     if (node != ep8248e_bcsr_node)
0119         return -ENODEV;
0120 
0121     ret = of_address_to_resource(ofdev->dev.of_node, 0, &res);
0122     if (ret)
0123         return ret;
0124 
0125     bus = alloc_mdio_bitbang(&ep8248e_mdio_ctrl);
0126     if (!bus)
0127         return -ENOMEM;
0128 
0129     bus->name = "ep8248e-mdio-bitbang";
0130     bus->parent = &ofdev->dev;
0131     snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
0132 
0133     ret = of_mdiobus_register(bus, ofdev->dev.of_node);
0134     if (ret)
0135         goto err_free_bus;
0136 
0137     return 0;
0138 err_free_bus:
0139     free_mdio_bitbang(bus);
0140     return ret;
0141 }
0142 
0143 static int ep8248e_mdio_remove(struct platform_device *ofdev)
0144 {
0145     BUG();
0146     return 0;
0147 }
0148 
0149 static const struct of_device_id ep8248e_mdio_match[] = {
0150     {
0151         .compatible = "fsl,ep8248e-mdio-bitbang",
0152     },
0153     {},
0154 };
0155 
0156 static struct platform_driver ep8248e_mdio_driver = {
0157     .driver = {
0158         .name = "ep8248e-mdio-bitbang",
0159         .of_match_table = ep8248e_mdio_match,
0160     },
0161     .probe = ep8248e_mdio_probe,
0162     .remove = ep8248e_mdio_remove,
0163 };
0164 
0165 struct cpm_pin {
0166     int port, pin, flags;
0167 };
0168 
0169 static __initdata struct cpm_pin ep8248e_pins[] = {
0170     /* SMC1 */
0171     {2, 4, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0172     {2, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0173 
0174     /* SCC1 */
0175     {2, 14, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0176     {2, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0177     {3, 29, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0178     {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
0179     {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0180 
0181     /* FCC1 */
0182     {0, 14, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0183     {0, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0184     {0, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0185     {0, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0186     {0, 18, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0187     {0, 19, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0188     {0, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0189     {0, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0190     {0, 26, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
0191     {0, 27, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
0192     {0, 28, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
0193     {0, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
0194     {0, 30, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
0195     {0, 31, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
0196     {2, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0197     {2, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0198 
0199     /* FCC2 */
0200     {1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0201     {1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0202     {1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0203     {1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0204     {1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0205     {1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0206     {1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0207     {1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0208     {1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0209     {1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0210     {1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0211     {1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
0212     {1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0213     {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0214     {2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0215     {2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0216 
0217     /* I2C */
0218     {4, 14, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
0219     {4, 15, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
0220 
0221     /* USB */
0222     {2, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0223     {2, 11, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0224     {2, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0225     {2, 24, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0226     {3, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0227     {3, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
0228     {3, 25, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
0229 };
0230 
0231 static void __init init_ioports(void)
0232 {
0233     int i;
0234 
0235     for (i = 0; i < ARRAY_SIZE(ep8248e_pins); i++) {
0236         const struct cpm_pin *pin = &ep8248e_pins[i];
0237         cpm2_set_pin(pin->port, pin->pin, pin->flags);
0238     }
0239 
0240     cpm2_smc_clk_setup(CPM_CLK_SMC1, CPM_BRG7);
0241     cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX);
0242     cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX);
0243     cpm2_clk_setup(CPM_CLK_SCC3, CPM_CLK8, CPM_CLK_TX); /* USB */
0244     cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK11, CPM_CLK_RX);
0245     cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK10, CPM_CLK_TX);
0246     cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX);
0247     cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX);
0248 }
0249 
0250 static void __init ep8248e_setup_arch(void)
0251 {
0252     if (ppc_md.progress)
0253         ppc_md.progress("ep8248e_setup_arch()", 0);
0254 
0255     cpm2_reset();
0256 
0257     /* When this is set, snooping CPM DMA from RAM causes
0258      * machine checks.  See erratum SIU18.
0259      */
0260     clrbits32(&cpm2_immr->im_siu_conf.siu_82xx.sc_bcr, MPC82XX_BCR_PLDP);
0261 
0262     ep8248e_bcsr_node =
0263         of_find_compatible_node(NULL, NULL, "fsl,ep8248e-bcsr");
0264     if (!ep8248e_bcsr_node) {
0265         printk(KERN_ERR "No bcsr in device tree\n");
0266         return;
0267     }
0268 
0269     ep8248e_bcsr = of_iomap(ep8248e_bcsr_node, 0);
0270     if (!ep8248e_bcsr) {
0271         printk(KERN_ERR "Cannot map BCSR registers\n");
0272         of_node_put(ep8248e_bcsr_node);
0273         ep8248e_bcsr_node = NULL;
0274         return;
0275     }
0276 
0277     setbits8(&ep8248e_bcsr[7], BCSR7_SCC2_ENABLE);
0278     setbits8(&ep8248e_bcsr[8], BCSR8_PHY1_ENABLE | BCSR8_PHY1_POWER |
0279                                BCSR8_PHY2_ENABLE | BCSR8_PHY2_POWER);
0280 
0281     init_ioports();
0282 
0283     if (ppc_md.progress)
0284         ppc_md.progress("ep8248e_setup_arch(), finish", 0);
0285 }
0286 
0287 static const struct of_device_id of_bus_ids[] __initconst = {
0288     { .compatible = "simple-bus", },
0289     { .compatible = "fsl,ep8248e-bcsr", },
0290     {},
0291 };
0292 
0293 static int __init declare_of_platform_devices(void)
0294 {
0295     of_platform_bus_probe(NULL, of_bus_ids, NULL);
0296 
0297     if (IS_ENABLED(CONFIG_MDIO_BITBANG))
0298         platform_driver_register(&ep8248e_mdio_driver);
0299 
0300     return 0;
0301 }
0302 machine_device_initcall(ep8248e, declare_of_platform_devices);
0303 
0304 /*
0305  * Called very early, device-tree isn't unflattened
0306  */
0307 static int __init ep8248e_probe(void)
0308 {
0309     return of_machine_is_compatible("fsl,ep8248e");
0310 }
0311 
0312 define_machine(ep8248e)
0313 {
0314     .name = "Embedded Planet EP8248E",
0315     .probe = ep8248e_probe,
0316     .setup_arch = ep8248e_setup_arch,
0317     .init_IRQ = ep8248e_pic_init,
0318     .get_irq = cpm2_get_irq,
0319     .calibrate_decr = generic_calibrate_decr,
0320     .restart = pq2_restart,
0321     .progress = udbg_progress,
0322 };