19724b86fSSylvain Munaut /*
29724b86fSSylvain Munaut  * Efika 5K2 platform code
39724b86fSSylvain Munaut  * Some code really inspired from the lite5200b platform.
49724b86fSSylvain Munaut  *
59724b86fSSylvain Munaut  * Copyright (C) 2006 bplan GmbH
69724b86fSSylvain Munaut  *
79724b86fSSylvain Munaut  * This file is licensed under the terms of the GNU General Public License
89724b86fSSylvain Munaut  * version 2. This program is licensed "as is" without any warranty of any
99724b86fSSylvain Munaut  * kind, whether express or implied.
109724b86fSSylvain Munaut  */
119724b86fSSylvain Munaut 
129724b86fSSylvain Munaut #include <linux/init.h>
13273b281fSSam Ravnborg #include <generated/utsrelease.h>
149724b86fSSylvain Munaut #include <linux/pci.h>
159fe2e796SGrant Likely #include <linux/of.h>
16308c09f1SLaura Abbott #include <asm/dma.h>
179724b86fSSylvain Munaut #include <asm/time.h>
189724b86fSSylvain Munaut #include <asm/machdep.h>
199724b86fSSylvain Munaut #include <asm/rtas.h>
209724b86fSSylvain Munaut #include <asm/mpc52xx.h>
219724b86fSSylvain Munaut 
229724b86fSSylvain Munaut #define EFIKA_PLATFORM_NAME "Efika"
239724b86fSSylvain Munaut 
249724b86fSSylvain Munaut 
259724b86fSSylvain Munaut /* ------------------------------------------------------------------------ */
269724b86fSSylvain Munaut /* PCI accesses thru RTAS                                                   */
279724b86fSSylvain Munaut /* ------------------------------------------------------------------------ */
289724b86fSSylvain Munaut 
299724b86fSSylvain Munaut #ifdef CONFIG_PCI
309724b86fSSylvain Munaut 
319724b86fSSylvain Munaut /*
329724b86fSSylvain Munaut  * Access functions for PCI config space using RTAS calls.
339724b86fSSylvain Munaut  */
rtas_read_config(struct pci_bus * bus,unsigned int devfn,int offset,int len,u32 * val)349724b86fSSylvain Munaut static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
359724b86fSSylvain Munaut 			    int len, u32 * val)
369724b86fSSylvain Munaut {
375b21fb8eSKumar Gala 	struct pci_controller *hose = pci_bus_to_host(bus);
389724b86fSSylvain Munaut 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
399724b86fSSylvain Munaut 	    | (((bus->number - hose->first_busno) & 0xff) << 16)
405516b540SKumar Gala 	    | (hose->global_number << 24);
419724b86fSSylvain Munaut 	int ret = -1;
429724b86fSSylvain Munaut 	int rval;
439724b86fSSylvain Munaut 
44*08273c9fSNathan Lynch 	rval = rtas_call(rtas_function_token(RTAS_FN_READ_PCI_CONFIG), 2, 2, &ret, addr, len);
459724b86fSSylvain Munaut 	*val = ret;
469724b86fSSylvain Munaut 	return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
479724b86fSSylvain Munaut }
489724b86fSSylvain Munaut 
rtas_write_config(struct pci_bus * bus,unsigned int devfn,int offset,int len,u32 val)499724b86fSSylvain Munaut static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
509724b86fSSylvain Munaut 			     int offset, int len, u32 val)
519724b86fSSylvain Munaut {
525b21fb8eSKumar Gala 	struct pci_controller *hose = pci_bus_to_host(bus);
539724b86fSSylvain Munaut 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
549724b86fSSylvain Munaut 	    | (((bus->number - hose->first_busno) & 0xff) << 16)
555516b540SKumar Gala 	    | (hose->global_number << 24);
569724b86fSSylvain Munaut 	int rval;
579724b86fSSylvain Munaut 
58*08273c9fSNathan Lynch 	rval = rtas_call(rtas_function_token(RTAS_FN_WRITE_PCI_CONFIG), 3, 1, NULL,
599724b86fSSylvain Munaut 			 addr, len, val);
609724b86fSSylvain Munaut 	return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
619724b86fSSylvain Munaut }
629724b86fSSylvain Munaut 
639724b86fSSylvain Munaut static struct pci_ops rtas_pci_ops = {
6421d8f6c7SNathan Lynch 	.read = rtas_read_config,
6521d8f6c7SNathan Lynch 	.write = rtas_write_config,
669724b86fSSylvain Munaut };
679724b86fSSylvain Munaut 
689724b86fSSylvain Munaut 
efika_pcisetup(void)69d3e0e028SDomen Puncer static void __init efika_pcisetup(void)
709724b86fSSylvain Munaut {
719724b86fSSylvain Munaut 	const int *bus_range;
729724b86fSSylvain Munaut 	int len;
739724b86fSSylvain Munaut 	struct pci_controller *hose;
749724b86fSSylvain Munaut 	struct device_node *root;
759724b86fSSylvain Munaut 	struct device_node *pcictrl;
769724b86fSSylvain Munaut 
779724b86fSSylvain Munaut 	root = of_find_node_by_path("/");
789724b86fSSylvain Munaut 	if (root == NULL) {
799724b86fSSylvain Munaut 		printk(KERN_WARNING EFIKA_PLATFORM_NAME
809724b86fSSylvain Munaut 		       ": Unable to find the root node\n");
819724b86fSSylvain Munaut 		return;
829724b86fSSylvain Munaut 	}
839724b86fSSylvain Munaut 
842c8e65b5SRob Herring 	for_each_child_of_node(root, pcictrl)
852c8e65b5SRob Herring 		if (of_node_name_eq(pcictrl, "pci"))
869724b86fSSylvain Munaut 			break;
879724b86fSSylvain Munaut 
889724b86fSSylvain Munaut 	of_node_put(root);
899724b86fSSylvain Munaut 
909724b86fSSylvain Munaut 	if (pcictrl == NULL) {
919724b86fSSylvain Munaut 		printk(KERN_WARNING EFIKA_PLATFORM_NAME
929724b86fSSylvain Munaut 		       ": Unable to find the PCI bridge node\n");
939724b86fSSylvain Munaut 		return;
949724b86fSSylvain Munaut 	}
959724b86fSSylvain Munaut 
96e2eb6392SStephen Rothwell 	bus_range = of_get_property(pcictrl, "bus-range", &len);
979724b86fSSylvain Munaut 	if (bus_range == NULL || len < 2 * sizeof(int)) {
989724b86fSSylvain Munaut 		printk(KERN_WARNING EFIKA_PLATFORM_NAME
99b7c670d6SRob Herring 		       ": Can't get bus-range for %pOF\n", pcictrl);
100915b9619SJulia Lawall 		goto out_put;
1019724b86fSSylvain Munaut 	}
1029724b86fSSylvain Munaut 
1039724b86fSSylvain Munaut 	if (bus_range[1] == bus_range[0])
1049724b86fSSylvain Munaut 		printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d",
1059724b86fSSylvain Munaut 		       bus_range[0]);
1069724b86fSSylvain Munaut 	else
1079724b86fSSylvain Munaut 		printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d",
1089724b86fSSylvain Munaut 		       bus_range[0], bus_range[1]);
109b7c670d6SRob Herring 	printk(" controlled by %pOF\n", pcictrl);
1109724b86fSSylvain Munaut 	printk("\n");
1119724b86fSSylvain Munaut 
112915b9619SJulia Lawall 	hose = pcibios_alloc_controller(pcictrl);
1139724b86fSSylvain Munaut 	if (!hose) {
1149724b86fSSylvain Munaut 		printk(KERN_WARNING EFIKA_PLATFORM_NAME
115b7c670d6SRob Herring 		       ": Can't allocate PCI controller structure for %pOF\n",
116b7c670d6SRob Herring 		       pcictrl);
117915b9619SJulia Lawall 		goto out_put;
1189724b86fSSylvain Munaut 	}
1199724b86fSSylvain Munaut 
1209724b86fSSylvain Munaut 	hose->first_busno = bus_range[0];
1219724b86fSSylvain Munaut 	hose->last_busno = bus_range[1];
1229724b86fSSylvain Munaut 	hose->ops = &rtas_pci_ops;
1239724b86fSSylvain Munaut 
1249724b86fSSylvain Munaut 	pci_process_bridge_OF_ranges(hose, pcictrl, 0);
125915b9619SJulia Lawall 	return;
126915b9619SJulia Lawall out_put:
127915b9619SJulia Lawall 	of_node_put(pcictrl);
1289724b86fSSylvain Munaut }
1299724b86fSSylvain Munaut 
1309724b86fSSylvain Munaut #else
efika_pcisetup(void)131d3e0e028SDomen Puncer static void __init efika_pcisetup(void)
1329724b86fSSylvain Munaut {}
1339724b86fSSylvain Munaut #endif
1349724b86fSSylvain Munaut 
1359724b86fSSylvain Munaut 
1369724b86fSSylvain Munaut 
1379724b86fSSylvain Munaut /* ------------------------------------------------------------------------ */
1389724b86fSSylvain Munaut /* Platform setup                                                           */
1399724b86fSSylvain Munaut /* ------------------------------------------------------------------------ */
1409724b86fSSylvain Munaut 
efika_show_cpuinfo(struct seq_file * m)1419724b86fSSylvain Munaut static void efika_show_cpuinfo(struct seq_file *m)
1429724b86fSSylvain Munaut {
1439724b86fSSylvain Munaut 	struct device_node *root;
144e2eb6392SStephen Rothwell 	const char *revision;
145e2eb6392SStephen Rothwell 	const char *codegendescription;
146e2eb6392SStephen Rothwell 	const char *codegenvendor;
1479724b86fSSylvain Munaut 
1489724b86fSSylvain Munaut 	root = of_find_node_by_path("/");
1499724b86fSSylvain Munaut 	if (!root)
1509724b86fSSylvain Munaut 		return;
1519724b86fSSylvain Munaut 
152e2eb6392SStephen Rothwell 	revision = of_get_property(root, "revision", NULL);
153e2eb6392SStephen Rothwell 	codegendescription = of_get_property(root, "CODEGEN,description", NULL);
154e2eb6392SStephen Rothwell 	codegenvendor = of_get_property(root, "CODEGEN,vendor", NULL);
1559724b86fSSylvain Munaut 
1569724b86fSSylvain Munaut 	if (codegendescription)
1579724b86fSSylvain Munaut 		seq_printf(m, "machine\t\t: %s\n", codegendescription);
1589724b86fSSylvain Munaut 	else
1599724b86fSSylvain Munaut 		seq_printf(m, "machine\t\t: Efika\n");
1609724b86fSSylvain Munaut 
1619724b86fSSylvain Munaut 	if (revision)
1629724b86fSSylvain Munaut 		seq_printf(m, "revision\t: %s\n", revision);
1639724b86fSSylvain Munaut 
1649724b86fSSylvain Munaut 	if (codegenvendor)
1659724b86fSSylvain Munaut 		seq_printf(m, "vendor\t\t: %s\n", codegenvendor);
1669724b86fSSylvain Munaut 
1679724b86fSSylvain Munaut 	of_node_put(root);
1689724b86fSSylvain Munaut }
1699724b86fSSylvain Munaut 
1702e1ee1f7SDomen Puncer #ifdef CONFIG_PM
efika_suspend_prepare(void __iomem * mbar)1712e1ee1f7SDomen Puncer static void efika_suspend_prepare(void __iomem *mbar)
1722e1ee1f7SDomen Puncer {
1732e1ee1f7SDomen Puncer 	u8 pin = 4;	/* GPIO_WKUP_4 (GPIO_PSC6_0 - IRDA_RX) */
1742e1ee1f7SDomen Puncer 	u8 level = 1;	/* wakeup on high level */
1752e1ee1f7SDomen Puncer 	/* IOW. to wake it up, short pins 1 and 3 on IRDA connector */
1762e1ee1f7SDomen Puncer 	mpc52xx_set_wakeup_gpio(pin, level);
1772e1ee1f7SDomen Puncer }
1782e1ee1f7SDomen Puncer #endif
1792e1ee1f7SDomen Puncer 
efika_setup_arch(void)1809724b86fSSylvain Munaut static void __init efika_setup_arch(void)
1819724b86fSSylvain Munaut {
1829724b86fSSylvain Munaut 	rtas_initialize();
1839724b86fSSylvain Munaut 
184c8004a28SGrant Likely 	/* Map important registers from the internal memory map */
185c8004a28SGrant Likely 	mpc52xx_map_common_devices();
186c8004a28SGrant Likely 
1872e1ee1f7SDomen Puncer #ifdef CONFIG_PM
1882e1ee1f7SDomen Puncer 	mpc52xx_suspend.board_suspend_prepare = efika_suspend_prepare;
1892e1ee1f7SDomen Puncer 	mpc52xx_pm_init();
1902e1ee1f7SDomen Puncer #endif
1912e1ee1f7SDomen Puncer 
1929724b86fSSylvain Munaut 	if (ppc_md.progress)
1939724b86fSSylvain Munaut 		ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n", 0x0);
1949724b86fSSylvain Munaut }
1959724b86fSSylvain Munaut 
efika_probe(void)1969724b86fSSylvain Munaut static int __init efika_probe(void)
1979724b86fSSylvain Munaut {
19856571384SBenjamin Herrenschmidt 	const char *model = of_get_property(of_root, "model", NULL);
1999724b86fSSylvain Munaut 
2009724b86fSSylvain Munaut 	if (model == NULL)
2019724b86fSSylvain Munaut 		return 0;
2029724b86fSSylvain Munaut 	if (strcmp(model, "EFIKA5K2"))
2039724b86fSSylvain Munaut 		return 0;
2049724b86fSSylvain Munaut 
2059724b86fSSylvain Munaut 	DMA_MODE_READ = 0x44;
2069724b86fSSylvain Munaut 	DMA_MODE_WRITE = 0x48;
2079724b86fSSylvain Munaut 
2089178ba29SAlexander Graf 	pm_power_off = rtas_power_off;
2099178ba29SAlexander Graf 
2109724b86fSSylvain Munaut 	return 1;
2119724b86fSSylvain Munaut }
2129724b86fSSylvain Munaut 
define_machine(efika)2139724b86fSSylvain Munaut define_machine(efika)
2149724b86fSSylvain Munaut {
2159724b86fSSylvain Munaut 	.name			= EFIKA_PLATFORM_NAME,
2169724b86fSSylvain Munaut 	.probe			= efika_probe,
2179724b86fSSylvain Munaut 	.setup_arch		= efika_setup_arch,
218eab3166fSOliver O'Halloran 	.discover_phbs		= efika_pcisetup,
2199724b86fSSylvain Munaut 	.init			= mpc52xx_declare_of_platform_devices,
2209724b86fSSylvain Munaut 	.show_cpuinfo		= efika_show_cpuinfo,
2219724b86fSSylvain Munaut 	.init_IRQ		= mpc52xx_init_irq,
2229724b86fSSylvain Munaut 	.get_irq		= mpc52xx_get_irq,
2239724b86fSSylvain Munaut 	.restart		= rtas_restart,
2249724b86fSSylvain Munaut 	.halt			= rtas_halt,
2259724b86fSSylvain Munaut 	.set_rtc_time		= rtas_set_rtc_time,
2269724b86fSSylvain Munaut 	.get_rtc_time		= rtas_get_rtc_time,
2279724b86fSSylvain Munaut 	.progress		= rtas_progress,
2289724b86fSSylvain Munaut 	.get_boot_time		= rtas_get_boot_time,
229d6658408SArnd Bergmann #ifdef CONFIG_PCI
2309724b86fSSylvain Munaut 	.phys_mem_access_prot	= pci_phys_mem_access_prot,
231d6658408SArnd Bergmann #endif
2329724b86fSSylvain Munaut };
2339724b86fSSylvain Munaut 
234