162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * This contain platform specific code for APM PPC460EX based Canyonlands
462306a36Sopenharmony_ci * board.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (c) 2010, Applied Micro Circuits Corporation
762306a36Sopenharmony_ci * Author: Rupjyoti Sarmah <rsarmah@apm.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci#include <linux/kernel.h>
1062306a36Sopenharmony_ci#include <linux/init.h>
1162306a36Sopenharmony_ci#include <asm/pci-bridge.h>
1262306a36Sopenharmony_ci#include <asm/ppc4xx.h>
1362306a36Sopenharmony_ci#include <asm/udbg.h>
1462306a36Sopenharmony_ci#include <asm/uic.h>
1562306a36Sopenharmony_ci#include <linux/of_address.h>
1662306a36Sopenharmony_ci#include <linux/of_platform.h>
1762306a36Sopenharmony_ci#include <linux/delay.h>
1862306a36Sopenharmony_ci#include "44x.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define BCSR_USB_EN	0x11
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistatic const struct of_device_id ppc460ex_of_bus[] __initconst = {
2362306a36Sopenharmony_ci	{ .compatible = "ibm,plb4", },
2462306a36Sopenharmony_ci	{ .compatible = "ibm,opb", },
2562306a36Sopenharmony_ci	{ .compatible = "ibm,ebc", },
2662306a36Sopenharmony_ci	{ .compatible = "simple-bus", },
2762306a36Sopenharmony_ci	{},
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic int __init ppc460ex_device_probe(void)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	of_platform_bus_probe(NULL, ppc460ex_of_bus, NULL);
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	return 0;
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_cimachine_device_initcall(canyonlands, ppc460ex_device_probe);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/* Using this code only for the Canyonlands board.  */
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic int __init ppc460ex_probe(void)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	pci_set_flags(PCI_REASSIGN_ALL_RSRC);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	return 1;
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/* USB PHY fixup code on Canyonlands kit. */
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic int __init ppc460ex_canyonlands_fixup(void)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	u8 __iomem *bcsr ;
5262306a36Sopenharmony_ci	void __iomem *vaddr;
5362306a36Sopenharmony_ci	struct device_node *np;
5462306a36Sopenharmony_ci	int ret = 0;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-bcsr");
5762306a36Sopenharmony_ci	if (!np) {
5862306a36Sopenharmony_ci		printk(KERN_ERR "failed did not find amcc, ppc460ex bcsr node\n");
5962306a36Sopenharmony_ci		return -ENODEV;
6062306a36Sopenharmony_ci	}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	bcsr = of_iomap(np, 0);
6362306a36Sopenharmony_ci	of_node_put(np);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	if (!bcsr) {
6662306a36Sopenharmony_ci		printk(KERN_CRIT "Could not remap bcsr\n");
6762306a36Sopenharmony_ci		ret = -ENODEV;
6862306a36Sopenharmony_ci		goto err_bcsr;
6962306a36Sopenharmony_ci	}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "ibm,ppc4xx-gpio");
7262306a36Sopenharmony_ci	if (!np) {
7362306a36Sopenharmony_ci		printk(KERN_ERR "failed did not find ibm,ppc4xx-gpio node\n");
7462306a36Sopenharmony_ci		return -ENODEV;
7562306a36Sopenharmony_ci	}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	vaddr = of_iomap(np, 0);
7862306a36Sopenharmony_ci	of_node_put(np);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	if (!vaddr) {
8162306a36Sopenharmony_ci		printk(KERN_CRIT "Could not get gpio node address\n");
8262306a36Sopenharmony_ci		ret = -ENODEV;
8362306a36Sopenharmony_ci		goto err_gpio;
8462306a36Sopenharmony_ci	}
8562306a36Sopenharmony_ci	/* Disable USB, through the BCSR7 bits */
8662306a36Sopenharmony_ci	setbits8(&bcsr[7], BCSR_USB_EN);
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	/* Wait for a while after reset */
8962306a36Sopenharmony_ci	msleep(100);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	/* Enable USB here */
9262306a36Sopenharmony_ci	clrbits8(&bcsr[7], BCSR_USB_EN);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	/*
9562306a36Sopenharmony_ci	 * Configure multiplexed gpio16 and gpio19 as alternate1 output
9662306a36Sopenharmony_ci	 * source after USB reset. In this configuration gpio16 will be
9762306a36Sopenharmony_ci	 * USB2HStop and gpio19 will be USB2DStop. For more details refer to
9862306a36Sopenharmony_ci	 * table 34-7 of PPC460EX user manual.
9962306a36Sopenharmony_ci	 */
10062306a36Sopenharmony_ci	setbits32((vaddr + GPIO0_OSRH), 0x42000000);
10162306a36Sopenharmony_ci	setbits32((vaddr + GPIO0_TSRH), 0x42000000);
10262306a36Sopenharmony_cierr_gpio:
10362306a36Sopenharmony_ci	iounmap(vaddr);
10462306a36Sopenharmony_cierr_bcsr:
10562306a36Sopenharmony_ci	iounmap(bcsr);
10662306a36Sopenharmony_ci	return ret;
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_cimachine_device_initcall(canyonlands, ppc460ex_canyonlands_fixup);
10962306a36Sopenharmony_cidefine_machine(canyonlands) {
11062306a36Sopenharmony_ci	.name = "Canyonlands",
11162306a36Sopenharmony_ci	.compatible = "amcc,canyonlands",
11262306a36Sopenharmony_ci	.probe = ppc460ex_probe,
11362306a36Sopenharmony_ci	.progress = udbg_progress,
11462306a36Sopenharmony_ci	.init_IRQ = uic_init_tree,
11562306a36Sopenharmony_ci	.get_irq = uic_get_irq,
11662306a36Sopenharmony_ci	.restart = ppc4xx_reset_system,
11762306a36Sopenharmony_ci};
118