xref: /linux/arch/mips/txx9/generic/setup.c (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
189d63fe1SAtsushi Nemoto /*
289d63fe1SAtsushi Nemoto  * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
389d63fe1SAtsushi Nemoto  *	    and RBTX49xx patch from CELF patch archive.
489d63fe1SAtsushi Nemoto  *
589d63fe1SAtsushi Nemoto  * 2003-2005 (c) MontaVista Software, Inc.
689d63fe1SAtsushi Nemoto  * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007
789d63fe1SAtsushi Nemoto  *
889d63fe1SAtsushi Nemoto  * This file is subject to the terms and conditions of the GNU General Public
989d63fe1SAtsushi Nemoto  * License.  See the file "COPYING" in the main directory of this archive
1089d63fe1SAtsushi Nemoto  * for more details.
1189d63fe1SAtsushi Nemoto  */
1289d63fe1SAtsushi Nemoto #include <linux/init.h>
1389d63fe1SAtsushi Nemoto #include <linux/kernel.h>
1489d63fe1SAtsushi Nemoto #include <linux/types.h>
15edcaf1a6SAtsushi Nemoto #include <linux/interrupt.h>
16edcaf1a6SAtsushi Nemoto #include <linux/string.h>
1726dd3e4fSPaul Gortmaker #include <linux/export.h>
1844ce9a9aSGeert Uytterhoeven #include <linux/clk-provider.h>
1944ce9a9aSGeert Uytterhoeven #include <linux/clkdev.h>
20edcaf1a6SAtsushi Nemoto #include <linux/err.h>
21be7658f7SLinus Walleij #include <linux/gpio/driver.h>
2268314725SAtsushi Nemoto #include <linux/platform_device.h>
23dc2865acSBoris Brezillon #include <linux/platform_data/txx9/ndfmc.h>
247779a5e0SAtsushi Nemoto #include <linux/serial_core.h>
2551f607c7SAtsushi Nemoto #include <linux/mtd/physmap.h>
26ae027eadSAtsushi Nemoto #include <linux/leds.h>
27269a3eb1SKay Sievers #include <linux/device.h>
285a0e3ad6STejun Heo #include <linux/slab.h>
2962e59c4eSStephen Boyd #include <linux/io.h>
30ca4d3e67SDavid Howells #include <linux/irq.h>
31edcaf1a6SAtsushi Nemoto #include <asm/bootinfo.h>
32bdc92d74SRalf Baechle #include <asm/idle.h>
33e0eb7307SAtsushi Nemoto #include <asm/time.h>
34a49297e8SAtsushi Nemoto #include <asm/reboot.h>
35d10e025fSAtsushi Nemoto #include <asm/r4kcache.h>
365c93316cSAlexander Sverdlin #include <asm/setup.h>
3789d63fe1SAtsushi Nemoto #include <asm/txx9/generic.h>
3807517529SAtsushi Nemoto #include <asm/txx9/pci.h>
39496a3b5cSAtsushi Nemoto #include <asm/txx9tmr.h>
40f48c8c95SAtsushi Nemoto #include <asm/txx9/dmac.h>
41edcaf1a6SAtsushi Nemoto #ifdef CONFIG_CPU_TX49XX
42edcaf1a6SAtsushi Nemoto #include <asm/txx9/tx4938.h>
43edcaf1a6SAtsushi Nemoto #endif
4489d63fe1SAtsushi Nemoto 
4589d63fe1SAtsushi Nemoto /* EBUSC settings of TX4927, etc. */
4689d63fe1SAtsushi Nemoto struct resource txx9_ce_res[8];
4789d63fe1SAtsushi Nemoto static char txx9_ce_res_name[8][4];	/* "CEn" */
4889d63fe1SAtsushi Nemoto 
4989d63fe1SAtsushi Nemoto /* pcode, internal register */
5094a4c329SAtsushi Nemoto unsigned int txx9_pcode;
5189d63fe1SAtsushi Nemoto char txx9_pcode_str[8];
5289d63fe1SAtsushi Nemoto static struct resource txx9_reg_res = {
5389d63fe1SAtsushi Nemoto 	.name = txx9_pcode_str,
5489d63fe1SAtsushi Nemoto 	.flags = IORESOURCE_MEM,
5589d63fe1SAtsushi Nemoto };
5689d63fe1SAtsushi Nemoto void __init
txx9_reg_res_init(unsigned int pcode,unsigned long base,unsigned long size)5789d63fe1SAtsushi Nemoto txx9_reg_res_init(unsigned int pcode, unsigned long base, unsigned long size)
5889d63fe1SAtsushi Nemoto {
5989d63fe1SAtsushi Nemoto 	int i;
6089d63fe1SAtsushi Nemoto 
6189d63fe1SAtsushi Nemoto 	for (i = 0; i < ARRAY_SIZE(txx9_ce_res); i++) {
6289d63fe1SAtsushi Nemoto 		sprintf(txx9_ce_res_name[i], "CE%d", i);
6389d63fe1SAtsushi Nemoto 		txx9_ce_res[i].flags = IORESOURCE_MEM;
6489d63fe1SAtsushi Nemoto 		txx9_ce_res[i].name = txx9_ce_res_name[i];
6589d63fe1SAtsushi Nemoto 	}
6689d63fe1SAtsushi Nemoto 
67073828d0SAtsushi Nemoto 	txx9_pcode = pcode;
6889d63fe1SAtsushi Nemoto 	sprintf(txx9_pcode_str, "TX%x", pcode);
6989d63fe1SAtsushi Nemoto 	if (base) {
7089d63fe1SAtsushi Nemoto 		txx9_reg_res.start = base & 0xfffffffffULL;
7189d63fe1SAtsushi Nemoto 		txx9_reg_res.end = (base & 0xfffffffffULL) + (size - 1);
7289d63fe1SAtsushi Nemoto 		request_resource(&iomem_resource, &txx9_reg_res);
7389d63fe1SAtsushi Nemoto 	}
7489d63fe1SAtsushi Nemoto }
7589d63fe1SAtsushi Nemoto 
7689d63fe1SAtsushi Nemoto /* clocks */
7789d63fe1SAtsushi Nemoto unsigned int txx9_master_clock;
7889d63fe1SAtsushi Nemoto unsigned int txx9_cpu_clock;
7989d63fe1SAtsushi Nemoto unsigned int txx9_gbus_clock;
80edcaf1a6SAtsushi Nemoto 
8194a4c329SAtsushi Nemoto int txx9_ccfg_toeon __initdata = 1;
82edcaf1a6SAtsushi Nemoto 
83860e546cSAtsushi Nemoto #define BOARD_VEC(board)	extern struct txx9_board_vec board;
84860e546cSAtsushi Nemoto #include <asm/txx9/boards.h>
85860e546cSAtsushi Nemoto #undef BOARD_VEC
86edcaf1a6SAtsushi Nemoto 
87edcaf1a6SAtsushi Nemoto struct txx9_board_vec *txx9_board_vec __initdata;
88edcaf1a6SAtsushi Nemoto static char txx9_system_type[32];
89edcaf1a6SAtsushi Nemoto 
90860e546cSAtsushi Nemoto static struct txx9_board_vec *board_vecs[] __initdata = {
91860e546cSAtsushi Nemoto #define BOARD_VEC(board)	&board,
92860e546cSAtsushi Nemoto #include <asm/txx9/boards.h>
93860e546cSAtsushi Nemoto #undef BOARD_VEC
94860e546cSAtsushi Nemoto };
95860e546cSAtsushi Nemoto 
find_board_byname(const char * name)96860e546cSAtsushi Nemoto static struct txx9_board_vec *__init find_board_byname(const char *name)
97860e546cSAtsushi Nemoto {
98860e546cSAtsushi Nemoto 	int i;
99860e546cSAtsushi Nemoto 
100860e546cSAtsushi Nemoto 	/* search board_vecs table */
101860e546cSAtsushi Nemoto 	for (i = 0; i < ARRAY_SIZE(board_vecs); i++) {
102860e546cSAtsushi Nemoto 		if (strstr(board_vecs[i]->system, name))
103860e546cSAtsushi Nemoto 			return board_vecs[i];
104860e546cSAtsushi Nemoto 	}
105860e546cSAtsushi Nemoto 	return NULL;
106860e546cSAtsushi Nemoto }
107860e546cSAtsushi Nemoto 
prom_init_cmdline(void)108e0dfb20cSAtsushi Nemoto static void __init prom_init_cmdline(void)
109edcaf1a6SAtsushi Nemoto {
11097b0511cSGeert Uytterhoeven 	int argc;
11197b0511cSGeert Uytterhoeven 	int *argv32;
112edcaf1a6SAtsushi Nemoto 	int i;			/* Always ignore the "-c" at argv[0] */
113edcaf1a6SAtsushi Nemoto 
11497b0511cSGeert Uytterhoeven 	if (fw_arg0 >= CKSEG0 || fw_arg1 < CKSEG0) {
11597b0511cSGeert Uytterhoeven 		/*
11697b0511cSGeert Uytterhoeven 		 * argc is not a valid number, or argv32 is not a valid
11797b0511cSGeert Uytterhoeven 		 * pointer
11897b0511cSGeert Uytterhoeven 		 */
11997b0511cSGeert Uytterhoeven 		argc = 0;
12097b0511cSGeert Uytterhoeven 		argv32 = NULL;
12197b0511cSGeert Uytterhoeven 	} else {
12297b0511cSGeert Uytterhoeven 		argc = (int)fw_arg0;
12397b0511cSGeert Uytterhoeven 		argv32 = (int *)fw_arg1;
12497b0511cSGeert Uytterhoeven 	}
12597b0511cSGeert Uytterhoeven 
126e0dfb20cSAtsushi Nemoto 	arcs_cmdline[0] = '\0';
127edcaf1a6SAtsushi Nemoto 
128edcaf1a6SAtsushi Nemoto 	for (i = 1; i < argc; i++) {
129e0dfb20cSAtsushi Nemoto 		char *str = (char *)(long)argv32[i];
130edcaf1a6SAtsushi Nemoto 		if (i != 1)
131edcaf1a6SAtsushi Nemoto 			strcat(arcs_cmdline, " ");
132e0dfb20cSAtsushi Nemoto 		if (strchr(str, ' ')) {
133e0dfb20cSAtsushi Nemoto 			strcat(arcs_cmdline, "\"");
134e0dfb20cSAtsushi Nemoto 			strcat(arcs_cmdline, str);
135e0dfb20cSAtsushi Nemoto 			strcat(arcs_cmdline, "\"");
136e0dfb20cSAtsushi Nemoto 		} else
137e0dfb20cSAtsushi Nemoto 			strcat(arcs_cmdline, str);
138e0dfb20cSAtsushi Nemoto 	}
139edcaf1a6SAtsushi Nemoto }
140edcaf1a6SAtsushi Nemoto 
141d10e025fSAtsushi Nemoto static int txx9_ic_disable __initdata;
142d10e025fSAtsushi Nemoto static int txx9_dc_disable __initdata;
143d10e025fSAtsushi Nemoto 
144d10e025fSAtsushi Nemoto #if defined(CONFIG_CPU_TX49XX)
145d10e025fSAtsushi Nemoto /* flush all cache on very early stage (before 4k_cache_init) */
early_flush_dcache(void)146d10e025fSAtsushi Nemoto static void __init early_flush_dcache(void)
147d10e025fSAtsushi Nemoto {
148d10e025fSAtsushi Nemoto 	unsigned int conf = read_c0_config();
149d10e025fSAtsushi Nemoto 	unsigned int dc_size = 1 << (12 + ((conf & CONF_DC) >> 6));
150d10e025fSAtsushi Nemoto 	unsigned int linesz = 32;
151d10e025fSAtsushi Nemoto 	unsigned long addr, end;
152d10e025fSAtsushi Nemoto 
153d10e025fSAtsushi Nemoto 	end = INDEX_BASE + dc_size / 4;
154d10e025fSAtsushi Nemoto 	/* 4way, waybit=0 */
155d10e025fSAtsushi Nemoto 	for (addr = INDEX_BASE; addr < end; addr += linesz) {
156d10e025fSAtsushi Nemoto 		cache_op(Index_Writeback_Inv_D, addr | 0);
157d10e025fSAtsushi Nemoto 		cache_op(Index_Writeback_Inv_D, addr | 1);
158d10e025fSAtsushi Nemoto 		cache_op(Index_Writeback_Inv_D, addr | 2);
159d10e025fSAtsushi Nemoto 		cache_op(Index_Writeback_Inv_D, addr | 3);
160d10e025fSAtsushi Nemoto 	}
161d10e025fSAtsushi Nemoto }
162d10e025fSAtsushi Nemoto 
txx9_cache_fixup(void)163d10e025fSAtsushi Nemoto static void __init txx9_cache_fixup(void)
164d10e025fSAtsushi Nemoto {
165d10e025fSAtsushi Nemoto 	unsigned int conf;
166d10e025fSAtsushi Nemoto 
167d10e025fSAtsushi Nemoto 	conf = read_c0_config();
168d10e025fSAtsushi Nemoto 	/* flush and disable */
169d10e025fSAtsushi Nemoto 	if (txx9_ic_disable) {
170d10e025fSAtsushi Nemoto 		conf |= TX49_CONF_IC;
171d10e025fSAtsushi Nemoto 		write_c0_config(conf);
172d10e025fSAtsushi Nemoto 	}
173d10e025fSAtsushi Nemoto 	if (txx9_dc_disable) {
174d10e025fSAtsushi Nemoto 		early_flush_dcache();
175d10e025fSAtsushi Nemoto 		conf |= TX49_CONF_DC;
176d10e025fSAtsushi Nemoto 		write_c0_config(conf);
177d10e025fSAtsushi Nemoto 	}
178d10e025fSAtsushi Nemoto 
179d10e025fSAtsushi Nemoto 	/* enable cache */
180d10e025fSAtsushi Nemoto 	conf = read_c0_config();
181d10e025fSAtsushi Nemoto 	if (!txx9_ic_disable)
182d10e025fSAtsushi Nemoto 		conf &= ~TX49_CONF_IC;
183d10e025fSAtsushi Nemoto 	if (!txx9_dc_disable)
184d10e025fSAtsushi Nemoto 		conf &= ~TX49_CONF_DC;
185d10e025fSAtsushi Nemoto 	write_c0_config(conf);
186d10e025fSAtsushi Nemoto 
187d10e025fSAtsushi Nemoto 	if (conf & TX49_CONF_IC)
188d10e025fSAtsushi Nemoto 		pr_info("TX49XX I-Cache disabled.\n");
189d10e025fSAtsushi Nemoto 	if (conf & TX49_CONF_DC)
190d10e025fSAtsushi Nemoto 		pr_info("TX49XX D-Cache disabled.\n");
191d10e025fSAtsushi Nemoto }
192d10e025fSAtsushi Nemoto #else
txx9_cache_fixup(void)193d10e025fSAtsushi Nemoto static inline void txx9_cache_fixup(void)
194d10e025fSAtsushi Nemoto {
195d10e025fSAtsushi Nemoto }
196d10e025fSAtsushi Nemoto #endif
197d10e025fSAtsushi Nemoto 
preprocess_cmdline(void)198860e546cSAtsushi Nemoto static void __init preprocess_cmdline(void)
199edcaf1a6SAtsushi Nemoto {
2007580c9c3SDmitri Vorobiev 	static char cmdline[COMMAND_LINE_SIZE] __initdata;
201860e546cSAtsushi Nemoto 	char *s;
202860e546cSAtsushi Nemoto 
203860e546cSAtsushi Nemoto 	strcpy(cmdline, arcs_cmdline);
204860e546cSAtsushi Nemoto 	s = cmdline;
205860e546cSAtsushi Nemoto 	arcs_cmdline[0] = '\0';
206860e546cSAtsushi Nemoto 	while (s && *s) {
207860e546cSAtsushi Nemoto 		char *str = strsep(&s, " ");
208860e546cSAtsushi Nemoto 		if (strncmp(str, "board=", 6) == 0) {
209860e546cSAtsushi Nemoto 			txx9_board_vec = find_board_byname(str + 6);
210860e546cSAtsushi Nemoto 			continue;
211860e546cSAtsushi Nemoto 		} else if (strncmp(str, "masterclk=", 10) == 0) {
2128e9ecbc5SDaniel Walter 			unsigned int val;
2138e9ecbc5SDaniel Walter 			if (kstrtouint(str + 10, 10, &val) == 0)
214860e546cSAtsushi Nemoto 				txx9_master_clock = val;
215860e546cSAtsushi Nemoto 			continue;
216d10e025fSAtsushi Nemoto 		} else if (strcmp(str, "icdisable") == 0) {
217d10e025fSAtsushi Nemoto 			txx9_ic_disable = 1;
218d10e025fSAtsushi Nemoto 			continue;
219d10e025fSAtsushi Nemoto 		} else if (strcmp(str, "dcdisable") == 0) {
220d10e025fSAtsushi Nemoto 			txx9_dc_disable = 1;
221d10e025fSAtsushi Nemoto 			continue;
222c7b95bcbSAtsushi Nemoto 		} else if (strcmp(str, "toeoff") == 0) {
223c7b95bcbSAtsushi Nemoto 			txx9_ccfg_toeon = 0;
224c7b95bcbSAtsushi Nemoto 			continue;
225c7b95bcbSAtsushi Nemoto 		} else if (strcmp(str, "toeon") == 0) {
226c7b95bcbSAtsushi Nemoto 			txx9_ccfg_toeon = 1;
227c7b95bcbSAtsushi Nemoto 			continue;
228860e546cSAtsushi Nemoto 		}
229860e546cSAtsushi Nemoto 		if (arcs_cmdline[0])
230860e546cSAtsushi Nemoto 			strcat(arcs_cmdline, " ");
231860e546cSAtsushi Nemoto 		strcat(arcs_cmdline, str);
232860e546cSAtsushi Nemoto 	}
233d10e025fSAtsushi Nemoto 
234d10e025fSAtsushi Nemoto 	txx9_cache_fixup();
235860e546cSAtsushi Nemoto }
236860e546cSAtsushi Nemoto 
select_board(void)237860e546cSAtsushi Nemoto static void __init select_board(void)
238860e546cSAtsushi Nemoto {
239860e546cSAtsushi Nemoto 	const char *envstr;
240860e546cSAtsushi Nemoto 
241860e546cSAtsushi Nemoto 	/* first, determine by "board=" argument in preprocess_cmdline() */
242860e546cSAtsushi Nemoto 	if (txx9_board_vec)
243860e546cSAtsushi Nemoto 		return;
244860e546cSAtsushi Nemoto 	/* next, determine by "board" envvar */
245860e546cSAtsushi Nemoto 	envstr = prom_getenv("board");
246860e546cSAtsushi Nemoto 	if (envstr) {
247860e546cSAtsushi Nemoto 		txx9_board_vec = find_board_byname(envstr);
248860e546cSAtsushi Nemoto 		if (txx9_board_vec)
249860e546cSAtsushi Nemoto 			return;
250860e546cSAtsushi Nemoto 	}
251860e546cSAtsushi Nemoto 
252860e546cSAtsushi Nemoto 	/* select "default" board */
253edcaf1a6SAtsushi Nemoto #ifdef CONFIG_CPU_TX49XX
254edcaf1a6SAtsushi Nemoto 	switch (TX4938_REV_PCODE()) {
2558d795f2aSAtsushi Nemoto #ifdef CONFIG_TOSHIBA_RBTX4927
256edcaf1a6SAtsushi Nemoto 	case 0x4927:
2577a1fdf19SYoichi Yuasa 		txx9_board_vec = &rbtx4927_vec;
258edcaf1a6SAtsushi Nemoto 		break;
259edcaf1a6SAtsushi Nemoto 	case 0x4937:
2607a1fdf19SYoichi Yuasa 		txx9_board_vec = &rbtx4937_vec;
261edcaf1a6SAtsushi Nemoto 		break;
2628d795f2aSAtsushi Nemoto #endif
263edcaf1a6SAtsushi Nemoto 	}
264edcaf1a6SAtsushi Nemoto #endif
265860e546cSAtsushi Nemoto }
266860e546cSAtsushi Nemoto 
prom_init(void)267860e546cSAtsushi Nemoto void __init prom_init(void)
268860e546cSAtsushi Nemoto {
269860e546cSAtsushi Nemoto 	prom_init_cmdline();
270860e546cSAtsushi Nemoto 	preprocess_cmdline();
271860e546cSAtsushi Nemoto 	select_board();
2727a1fdf19SYoichi Yuasa 
273edcaf1a6SAtsushi Nemoto 	strcpy(txx9_system_type, txx9_board_vec->system);
2747a1fdf19SYoichi Yuasa 
2757b226094SAtsushi Nemoto 	txx9_board_vec->prom_init();
276edcaf1a6SAtsushi Nemoto }
277edcaf1a6SAtsushi Nemoto 
get_system_type(void)278edcaf1a6SAtsushi Nemoto const char *get_system_type(void)
279edcaf1a6SAtsushi Nemoto {
280edcaf1a6SAtsushi Nemoto 	return txx9_system_type;
281edcaf1a6SAtsushi Nemoto }
282edcaf1a6SAtsushi Nemoto 
prom_getenv(const char * name)283265b89dbSAtsushi Nemoto const char *__init prom_getenv(const char *name)
284265b89dbSAtsushi Nemoto {
28597b0511cSGeert Uytterhoeven 	const s32 *str;
286265b89dbSAtsushi Nemoto 
28797b0511cSGeert Uytterhoeven 	if (fw_arg2 < CKSEG0)
288265b89dbSAtsushi Nemoto 		return NULL;
28997b0511cSGeert Uytterhoeven 
29097b0511cSGeert Uytterhoeven 	str = (const s32 *)fw_arg2;
291265b89dbSAtsushi Nemoto 	/* YAMON style ("name", "value" pairs) */
292265b89dbSAtsushi Nemoto 	while (str[0] && str[1]) {
293265b89dbSAtsushi Nemoto 		if (!strcmp((const char *)(unsigned long)str[0], name))
294265b89dbSAtsushi Nemoto 			return (const char *)(unsigned long)str[1];
295265b89dbSAtsushi Nemoto 		str += 2;
296265b89dbSAtsushi Nemoto 	}
297265b89dbSAtsushi Nemoto 	return NULL;
298265b89dbSAtsushi Nemoto }
299265b89dbSAtsushi Nemoto 
txx9_machine_halt(void)300a49297e8SAtsushi Nemoto static void __noreturn txx9_machine_halt(void)
301a49297e8SAtsushi Nemoto {
302a49297e8SAtsushi Nemoto 	local_irq_disable();
303a49297e8SAtsushi Nemoto 	clear_c0_status(ST0_IM);
304a49297e8SAtsushi Nemoto 	while (1) {
305a49297e8SAtsushi Nemoto 		if (cpu_wait) {
306a49297e8SAtsushi Nemoto 			(*cpu_wait)();
307a49297e8SAtsushi Nemoto 			if (cpu_has_counter) {
308a49297e8SAtsushi Nemoto 				/*
309a49297e8SAtsushi Nemoto 				 * Clear counter interrupt while it
310a49297e8SAtsushi Nemoto 				 * breaks WAIT instruction even if
311a49297e8SAtsushi Nemoto 				 * masked.
312a49297e8SAtsushi Nemoto 				 */
313a49297e8SAtsushi Nemoto 				write_c0_compare(0);
314a49297e8SAtsushi Nemoto 			}
315a49297e8SAtsushi Nemoto 		}
316a49297e8SAtsushi Nemoto 	}
317a49297e8SAtsushi Nemoto }
318a49297e8SAtsushi Nemoto 
31968314725SAtsushi Nemoto /* Watchdog support */
txx9_wdt_init(unsigned long base)32068314725SAtsushi Nemoto void __init txx9_wdt_init(unsigned long base)
32168314725SAtsushi Nemoto {
32268314725SAtsushi Nemoto 	struct resource res = {
32368314725SAtsushi Nemoto 		.start	= base,
32468314725SAtsushi Nemoto 		.end	= base + 0x100 - 1,
32568314725SAtsushi Nemoto 		.flags	= IORESOURCE_MEM,
32668314725SAtsushi Nemoto 	};
32768314725SAtsushi Nemoto 	platform_device_register_simple("txx9wdt", -1, &res, 1);
32868314725SAtsushi Nemoto }
32968314725SAtsushi Nemoto 
txx9_wdt_now(unsigned long base)330496a3b5cSAtsushi Nemoto void txx9_wdt_now(unsigned long base)
331496a3b5cSAtsushi Nemoto {
332496a3b5cSAtsushi Nemoto 	struct txx9_tmr_reg __iomem *tmrptr =
333496a3b5cSAtsushi Nemoto 		ioremap(base, sizeof(struct txx9_tmr_reg));
334496a3b5cSAtsushi Nemoto 	/* disable watch dog timer */
335496a3b5cSAtsushi Nemoto 	__raw_writel(TXx9_TMWTMR_WDIS | TXx9_TMWTMR_TWC, &tmrptr->wtmr);
336496a3b5cSAtsushi Nemoto 	__raw_writel(0, &tmrptr->tcr);
337496a3b5cSAtsushi Nemoto 	/* kick watchdog */
338496a3b5cSAtsushi Nemoto 	__raw_writel(TXx9_TMWTMR_TWIE, &tmrptr->wtmr);
339496a3b5cSAtsushi Nemoto 	__raw_writel(1, &tmrptr->cpra); /* immediate */
340496a3b5cSAtsushi Nemoto 	__raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG,
341496a3b5cSAtsushi Nemoto 		     &tmrptr->tcr);
342496a3b5cSAtsushi Nemoto }
343496a3b5cSAtsushi Nemoto 
344c49f91f5SAtsushi Nemoto /* SPI support */
txx9_spi_init(int busid,unsigned long base,int irq)345c49f91f5SAtsushi Nemoto void __init txx9_spi_init(int busid, unsigned long base, int irq)
346c49f91f5SAtsushi Nemoto {
347c49f91f5SAtsushi Nemoto 	struct resource res[] = {
348c49f91f5SAtsushi Nemoto 		{
349c49f91f5SAtsushi Nemoto 			.start	= base,
350c49f91f5SAtsushi Nemoto 			.end	= base + 0x20 - 1,
351c49f91f5SAtsushi Nemoto 			.flags	= IORESOURCE_MEM,
352c49f91f5SAtsushi Nemoto 		}, {
353c49f91f5SAtsushi Nemoto 			.start	= irq,
354c49f91f5SAtsushi Nemoto 			.flags	= IORESOURCE_IRQ,
355c49f91f5SAtsushi Nemoto 		},
356c49f91f5SAtsushi Nemoto 	};
357c49f91f5SAtsushi Nemoto 	platform_device_register_simple("spi_txx9", busid,
358c49f91f5SAtsushi Nemoto 					res, ARRAY_SIZE(res));
359c49f91f5SAtsushi Nemoto }
360c49f91f5SAtsushi Nemoto 
txx9_ethaddr_init(unsigned int id,unsigned char * ethaddr)361c49f91f5SAtsushi Nemoto void __init txx9_ethaddr_init(unsigned int id, unsigned char *ethaddr)
362c49f91f5SAtsushi Nemoto {
363c49f91f5SAtsushi Nemoto 	struct platform_device *pdev =
364c49f91f5SAtsushi Nemoto 		platform_device_alloc("tc35815-mac", id);
365c49f91f5SAtsushi Nemoto 	if (!pdev ||
366c49f91f5SAtsushi Nemoto 	    platform_device_add_data(pdev, ethaddr, 6) ||
367c49f91f5SAtsushi Nemoto 	    platform_device_add(pdev))
368c49f91f5SAtsushi Nemoto 		platform_device_put(pdev);
369c49f91f5SAtsushi Nemoto }
370c49f91f5SAtsushi Nemoto 
txx9_sio_init(unsigned long baseaddr,int irq,unsigned int line,unsigned int sclk,int nocts)3717779a5e0SAtsushi Nemoto void __init txx9_sio_init(unsigned long baseaddr, int irq,
3727779a5e0SAtsushi Nemoto 			  unsigned int line, unsigned int sclk, int nocts)
3737779a5e0SAtsushi Nemoto {
3747779a5e0SAtsushi Nemoto #ifdef CONFIG_SERIAL_TXX9
3757779a5e0SAtsushi Nemoto 	struct uart_port req;
3767779a5e0SAtsushi Nemoto 
3777779a5e0SAtsushi Nemoto 	memset(&req, 0, sizeof(req));
3787779a5e0SAtsushi Nemoto 	req.line = line;
3797779a5e0SAtsushi Nemoto 	req.iotype = UPIO_MEM;
3807779a5e0SAtsushi Nemoto 	req.membase = ioremap(baseaddr, 0x24);
3817779a5e0SAtsushi Nemoto 	req.mapbase = baseaddr;
3827779a5e0SAtsushi Nemoto 	req.irq = irq;
3837779a5e0SAtsushi Nemoto 	if (!nocts)
3847779a5e0SAtsushi Nemoto 		req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
3857779a5e0SAtsushi Nemoto 	if (sclk) {
3867779a5e0SAtsushi Nemoto 		req.flags |= UPF_MAGIC_MULTIPLIER /*USE_SCLK*/;
3877779a5e0SAtsushi Nemoto 		req.uartclk = sclk;
3887779a5e0SAtsushi Nemoto 	} else
3897779a5e0SAtsushi Nemoto 		req.uartclk = TXX9_IMCLK;
3907779a5e0SAtsushi Nemoto 	early_serial_txx9_setup(&req);
3917779a5e0SAtsushi Nemoto #endif /* CONFIG_SERIAL_TXX9 */
3927779a5e0SAtsushi Nemoto }
3937779a5e0SAtsushi Nemoto 
394e352953cSAtsushi Nemoto #ifdef CONFIG_EARLY_PRINTK
null_prom_putchar(char c)395f7be4e75SAaro Koskinen static void null_prom_putchar(char c)
396e352953cSAtsushi Nemoto {
397e352953cSAtsushi Nemoto }
398f7be4e75SAaro Koskinen void (*txx9_prom_putchar)(char c) = null_prom_putchar;
399e352953cSAtsushi Nemoto 
prom_putchar(char c)400f7be4e75SAaro Koskinen void prom_putchar(char c)
401e352953cSAtsushi Nemoto {
402e352953cSAtsushi Nemoto 	txx9_prom_putchar(c);
403e352953cSAtsushi Nemoto }
404e352953cSAtsushi Nemoto 
405e352953cSAtsushi Nemoto static void __iomem *early_txx9_sio_port;
406e352953cSAtsushi Nemoto 
early_txx9_sio_putchar(char c)407f7be4e75SAaro Koskinen static void early_txx9_sio_putchar(char c)
408e352953cSAtsushi Nemoto {
409e352953cSAtsushi Nemoto #define TXX9_SICISR	0x0c
410e352953cSAtsushi Nemoto #define TXX9_SITFIFO	0x1c
411e352953cSAtsushi Nemoto #define TXX9_SICISR_TXALS	0x00000002
412e352953cSAtsushi Nemoto 	while (!(__raw_readl(early_txx9_sio_port + TXX9_SICISR) &
413e352953cSAtsushi Nemoto 		 TXX9_SICISR_TXALS))
414e352953cSAtsushi Nemoto 		;
415e352953cSAtsushi Nemoto 	__raw_writel(c, early_txx9_sio_port + TXX9_SITFIFO);
416e352953cSAtsushi Nemoto }
417e352953cSAtsushi Nemoto 
txx9_sio_putchar_init(unsigned long baseaddr)418e352953cSAtsushi Nemoto void __init txx9_sio_putchar_init(unsigned long baseaddr)
419e352953cSAtsushi Nemoto {
420e352953cSAtsushi Nemoto 	early_txx9_sio_port = ioremap(baseaddr, 0x24);
421e352953cSAtsushi Nemoto 	txx9_prom_putchar = early_txx9_sio_putchar;
422e352953cSAtsushi Nemoto }
423e352953cSAtsushi Nemoto #endif /* CONFIG_EARLY_PRINTK */
424e352953cSAtsushi Nemoto 
425edcaf1a6SAtsushi Nemoto /* wrappers */
plat_mem_setup(void)426edcaf1a6SAtsushi Nemoto void __init plat_mem_setup(void)
427edcaf1a6SAtsushi Nemoto {
42894a4c329SAtsushi Nemoto 	ioport_resource.start = 0;
42994a4c329SAtsushi Nemoto 	ioport_resource.end = ~0UL;	/* no limit */
43094a4c329SAtsushi Nemoto 	iomem_resource.start = 0;
43194a4c329SAtsushi Nemoto 	iomem_resource.end = ~0UL;	/* no limit */
432a49297e8SAtsushi Nemoto 
433a49297e8SAtsushi Nemoto 	/* fallback restart/halt routines */
434a49297e8SAtsushi Nemoto 	_machine_restart = (void (*)(char *))txx9_machine_halt;
435a49297e8SAtsushi Nemoto 	_machine_halt = txx9_machine_halt;
436a49297e8SAtsushi Nemoto 	pm_power_off = txx9_machine_halt;
437a49297e8SAtsushi Nemoto 
43807517529SAtsushi Nemoto #ifdef CONFIG_PCI
43907517529SAtsushi Nemoto 	pcibios_plat_setup = txx9_pcibios_setup;
44007517529SAtsushi Nemoto #endif
441edcaf1a6SAtsushi Nemoto 	txx9_board_vec->mem_setup();
442edcaf1a6SAtsushi Nemoto }
443edcaf1a6SAtsushi Nemoto 
arch_init_irq(void)444edcaf1a6SAtsushi Nemoto void __init arch_init_irq(void)
445edcaf1a6SAtsushi Nemoto {
446edcaf1a6SAtsushi Nemoto 	txx9_board_vec->irq_setup();
447edcaf1a6SAtsushi Nemoto }
448edcaf1a6SAtsushi Nemoto 
plat_time_init(void)449edcaf1a6SAtsushi Nemoto void __init plat_time_init(void)
450edcaf1a6SAtsushi Nemoto {
4511374d084SAtsushi Nemoto #ifdef CONFIG_CPU_TX49XX
4521374d084SAtsushi Nemoto 	mips_hpt_frequency = txx9_cpu_clock / 2;
4531374d084SAtsushi Nemoto #endif
454edcaf1a6SAtsushi Nemoto 	txx9_board_vec->time_init();
455edcaf1a6SAtsushi Nemoto }
456edcaf1a6SAtsushi Nemoto 
txx9_clk_init(void)45744ce9a9aSGeert Uytterhoeven static void txx9_clk_init(void)
45844ce9a9aSGeert Uytterhoeven {
45944ce9a9aSGeert Uytterhoeven 	struct clk_hw *hw;
46044ce9a9aSGeert Uytterhoeven 	int error;
46144ce9a9aSGeert Uytterhoeven 
46244ce9a9aSGeert Uytterhoeven 	hw = clk_hw_register_fixed_rate(NULL, "gbus", NULL, 0, txx9_gbus_clock);
46344ce9a9aSGeert Uytterhoeven 	if (IS_ERR(hw)) {
46444ce9a9aSGeert Uytterhoeven 		error = PTR_ERR(hw);
46544ce9a9aSGeert Uytterhoeven 		goto fail;
46644ce9a9aSGeert Uytterhoeven 	}
46744ce9a9aSGeert Uytterhoeven 
46844ce9a9aSGeert Uytterhoeven 	hw = clk_hw_register_fixed_factor(NULL, "imbus", "gbus", 0, 1, 2);
46944ce9a9aSGeert Uytterhoeven 	error = clk_hw_register_clkdev(hw, "imbus_clk", NULL);
47044ce9a9aSGeert Uytterhoeven 	if (error)
47144ce9a9aSGeert Uytterhoeven 		goto fail;
47244ce9a9aSGeert Uytterhoeven 
47344ce9a9aSGeert Uytterhoeven #ifdef CONFIG_CPU_TX49XX
47444ce9a9aSGeert Uytterhoeven 	if (TX4938_REV_PCODE() == 0x4938) {
47544ce9a9aSGeert Uytterhoeven 		hw = clk_hw_register_fixed_factor(NULL, "spi", "gbus", 0, 1, 4);
47644ce9a9aSGeert Uytterhoeven 		error = clk_hw_register_clkdev(hw, "spi-baseclk", NULL);
47744ce9a9aSGeert Uytterhoeven 		if (error)
47844ce9a9aSGeert Uytterhoeven 			goto fail;
47944ce9a9aSGeert Uytterhoeven 	}
48044ce9a9aSGeert Uytterhoeven #endif
48144ce9a9aSGeert Uytterhoeven 
48244ce9a9aSGeert Uytterhoeven 	return;
48344ce9a9aSGeert Uytterhoeven 
48444ce9a9aSGeert Uytterhoeven fail:
48544ce9a9aSGeert Uytterhoeven 	pr_err("Failed to register clocks: %d\n", error);
48644ce9a9aSGeert Uytterhoeven }
48744ce9a9aSGeert Uytterhoeven 
_txx9_arch_init(void)488edcaf1a6SAtsushi Nemoto static int __init _txx9_arch_init(void)
489edcaf1a6SAtsushi Nemoto {
49044ce9a9aSGeert Uytterhoeven 	txx9_clk_init();
49144ce9a9aSGeert Uytterhoeven 
492edcaf1a6SAtsushi Nemoto 	if (txx9_board_vec->arch_init)
493edcaf1a6SAtsushi Nemoto 		txx9_board_vec->arch_init();
494edcaf1a6SAtsushi Nemoto 	return 0;
495edcaf1a6SAtsushi Nemoto }
496edcaf1a6SAtsushi Nemoto arch_initcall(_txx9_arch_init);
497edcaf1a6SAtsushi Nemoto 
_txx9_device_init(void)498edcaf1a6SAtsushi Nemoto static int __init _txx9_device_init(void)
499edcaf1a6SAtsushi Nemoto {
500edcaf1a6SAtsushi Nemoto 	if (txx9_board_vec->device_init)
501edcaf1a6SAtsushi Nemoto 		txx9_board_vec->device_init();
502edcaf1a6SAtsushi Nemoto 	return 0;
503edcaf1a6SAtsushi Nemoto }
504edcaf1a6SAtsushi Nemoto device_initcall(_txx9_device_init);
505edcaf1a6SAtsushi Nemoto 
506edcaf1a6SAtsushi Nemoto int (*txx9_irq_dispatch)(int pending);
plat_irq_dispatch(void)507edcaf1a6SAtsushi Nemoto asmlinkage void plat_irq_dispatch(void)
508edcaf1a6SAtsushi Nemoto {
509edcaf1a6SAtsushi Nemoto 	int pending = read_c0_status() & read_c0_cause() & ST0_IM;
510edcaf1a6SAtsushi Nemoto 	int irq = txx9_irq_dispatch(pending);
511edcaf1a6SAtsushi Nemoto 
512edcaf1a6SAtsushi Nemoto 	if (likely(irq >= 0))
513edcaf1a6SAtsushi Nemoto 		do_IRQ(irq);
514edcaf1a6SAtsushi Nemoto 	else
515edcaf1a6SAtsushi Nemoto 		spurious_interrupt();
516edcaf1a6SAtsushi Nemoto }
5174c642f3fSAtsushi Nemoto 
5184c642f3fSAtsushi Nemoto /* see include/asm-mips/mach-tx39xx/mangle-port.h, for example. */
5194c642f3fSAtsushi Nemoto #ifdef NEEDS_TXX9_SWIZZLE_ADDR_B
__swizzle_addr_none(unsigned long port)5204c642f3fSAtsushi Nemoto static unsigned long __swizzle_addr_none(unsigned long port)
5214c642f3fSAtsushi Nemoto {
5224c642f3fSAtsushi Nemoto 	return port;
5234c642f3fSAtsushi Nemoto }
5244c642f3fSAtsushi Nemoto unsigned long (*__swizzle_addr_b)(unsigned long port) = __swizzle_addr_none;
5254c642f3fSAtsushi Nemoto EXPORT_SYMBOL(__swizzle_addr_b);
5264c642f3fSAtsushi Nemoto #endif
52751f607c7SAtsushi Nemoto 
txx9_physmap_flash_init(int no,unsigned long addr,unsigned long size,const struct physmap_flash_data * pdata)52851f607c7SAtsushi Nemoto void __init txx9_physmap_flash_init(int no, unsigned long addr,
52951f607c7SAtsushi Nemoto 				    unsigned long size,
53051f607c7SAtsushi Nemoto 				    const struct physmap_flash_data *pdata)
53151f607c7SAtsushi Nemoto {
532b33b4407SFlorian Fainelli #if IS_ENABLED(CONFIG_MTD_PHYSMAP)
53351f607c7SAtsushi Nemoto 	struct resource res = {
53451f607c7SAtsushi Nemoto 		.start = addr,
53551f607c7SAtsushi Nemoto 		.end = addr + size - 1,
53651f607c7SAtsushi Nemoto 		.flags = IORESOURCE_MEM,
53751f607c7SAtsushi Nemoto 	};
53851f607c7SAtsushi Nemoto 	struct platform_device *pdev;
53951f607c7SAtsushi Nemoto 	static struct mtd_partition parts[2];
54051f607c7SAtsushi Nemoto 	struct physmap_flash_data pdata_part;
54151f607c7SAtsushi Nemoto 
54251f607c7SAtsushi Nemoto 	/* If this area contained boot area, make separate partition */
54351f607c7SAtsushi Nemoto 	if (pdata->nr_parts == 0 && !pdata->parts &&
54451f607c7SAtsushi Nemoto 	    addr < 0x1fc00000 && addr + size > 0x1fc00000 &&
54551f607c7SAtsushi Nemoto 	    !parts[0].name) {
54651f607c7SAtsushi Nemoto 		parts[0].name = "boot";
54751f607c7SAtsushi Nemoto 		parts[0].offset = 0x1fc00000 - addr;
54851f607c7SAtsushi Nemoto 		parts[0].size = addr + size - 0x1fc00000;
54951f607c7SAtsushi Nemoto 		parts[1].name = "user";
55051f607c7SAtsushi Nemoto 		parts[1].offset = 0;
55151f607c7SAtsushi Nemoto 		parts[1].size = 0x1fc00000 - addr;
55251f607c7SAtsushi Nemoto 		pdata_part = *pdata;
55351f607c7SAtsushi Nemoto 		pdata_part.nr_parts = ARRAY_SIZE(parts);
55451f607c7SAtsushi Nemoto 		pdata_part.parts = parts;
55551f607c7SAtsushi Nemoto 		pdata = &pdata_part;
55651f607c7SAtsushi Nemoto 	}
55747854888SJamie Iles 
55851f607c7SAtsushi Nemoto 	pdev = platform_device_alloc("physmap-flash", no);
55951f607c7SAtsushi Nemoto 	if (!pdev ||
56051f607c7SAtsushi Nemoto 	    platform_device_add_resources(pdev, &res, 1) ||
56151f607c7SAtsushi Nemoto 	    platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
56251f607c7SAtsushi Nemoto 	    platform_device_add(pdev))
56351f607c7SAtsushi Nemoto 		platform_device_put(pdev);
56451f607c7SAtsushi Nemoto #endif
56551f607c7SAtsushi Nemoto }
566ae027eadSAtsushi Nemoto 
txx9_ndfmc_init(unsigned long baseaddr,const struct txx9ndfmc_platform_data * pdata)567a591f5d3SAtsushi Nemoto void __init txx9_ndfmc_init(unsigned long baseaddr,
568a591f5d3SAtsushi Nemoto 			    const struct txx9ndfmc_platform_data *pdata)
569a591f5d3SAtsushi Nemoto {
570b33b4407SFlorian Fainelli #if IS_ENABLED(CONFIG_MTD_NAND_TXX9NDFMC)
571a591f5d3SAtsushi Nemoto 	struct resource res = {
572a591f5d3SAtsushi Nemoto 		.start = baseaddr,
573a591f5d3SAtsushi Nemoto 		.end = baseaddr + 0x1000 - 1,
574a591f5d3SAtsushi Nemoto 		.flags = IORESOURCE_MEM,
575a591f5d3SAtsushi Nemoto 	};
576a591f5d3SAtsushi Nemoto 	struct platform_device *pdev = platform_device_alloc("txx9ndfmc", -1);
577a591f5d3SAtsushi Nemoto 
578a591f5d3SAtsushi Nemoto 	if (!pdev ||
579a591f5d3SAtsushi Nemoto 	    platform_device_add_resources(pdev, &res, 1) ||
580a591f5d3SAtsushi Nemoto 	    platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
581a591f5d3SAtsushi Nemoto 	    platform_device_add(pdev))
582a591f5d3SAtsushi Nemoto 		platform_device_put(pdev);
583a591f5d3SAtsushi Nemoto #endif
584a591f5d3SAtsushi Nemoto }
585a591f5d3SAtsushi Nemoto 
586b33b4407SFlorian Fainelli #if IS_ENABLED(CONFIG_LEDS_GPIO)
587ae027eadSAtsushi Nemoto static DEFINE_SPINLOCK(txx9_iocled_lock);
588ae027eadSAtsushi Nemoto 
589ae027eadSAtsushi Nemoto #define TXX9_IOCLED_MAXLEDS 8
590ae027eadSAtsushi Nemoto 
591ae027eadSAtsushi Nemoto struct txx9_iocled_data {
592ae027eadSAtsushi Nemoto 	struct gpio_chip chip;
593ae027eadSAtsushi Nemoto 	u8 cur_val;
594ae027eadSAtsushi Nemoto 	void __iomem *mmioaddr;
595ae027eadSAtsushi Nemoto 	struct gpio_led_platform_data pdata;
596ae027eadSAtsushi Nemoto 	struct gpio_led leds[TXX9_IOCLED_MAXLEDS];
597ae027eadSAtsushi Nemoto 	char names[TXX9_IOCLED_MAXLEDS][32];
598ae027eadSAtsushi Nemoto };
599ae027eadSAtsushi Nemoto 
txx9_iocled_get(struct gpio_chip * chip,unsigned int offset)600ae027eadSAtsushi Nemoto static int txx9_iocled_get(struct gpio_chip *chip, unsigned int offset)
601ae027eadSAtsushi Nemoto {
602be7658f7SLinus Walleij 	struct txx9_iocled_data *data = gpiochip_get_data(chip);
6038cbe4b5cSLinus Walleij 	return !!(data->cur_val & (1 << offset));
604ae027eadSAtsushi Nemoto }
605ae027eadSAtsushi Nemoto 
txx9_iocled_set(struct gpio_chip * chip,unsigned int offset,int value)606ae027eadSAtsushi Nemoto static void txx9_iocled_set(struct gpio_chip *chip, unsigned int offset,
607ae027eadSAtsushi Nemoto 			    int value)
608ae027eadSAtsushi Nemoto {
609be7658f7SLinus Walleij 	struct txx9_iocled_data *data = gpiochip_get_data(chip);
610ae027eadSAtsushi Nemoto 	unsigned long flags;
611ae027eadSAtsushi Nemoto 	spin_lock_irqsave(&txx9_iocled_lock, flags);
612ae027eadSAtsushi Nemoto 	if (value)
613ae027eadSAtsushi Nemoto 		data->cur_val |= 1 << offset;
614ae027eadSAtsushi Nemoto 	else
615ae027eadSAtsushi Nemoto 		data->cur_val &= ~(1 << offset);
616ae027eadSAtsushi Nemoto 	writeb(data->cur_val, data->mmioaddr);
617ae027eadSAtsushi Nemoto 	mmiowb();
618ae027eadSAtsushi Nemoto 	spin_unlock_irqrestore(&txx9_iocled_lock, flags);
619ae027eadSAtsushi Nemoto }
620ae027eadSAtsushi Nemoto 
txx9_iocled_dir_in(struct gpio_chip * chip,unsigned int offset)621ae027eadSAtsushi Nemoto static int txx9_iocled_dir_in(struct gpio_chip *chip, unsigned int offset)
622ae027eadSAtsushi Nemoto {
623ae027eadSAtsushi Nemoto 	return 0;
624ae027eadSAtsushi Nemoto }
625ae027eadSAtsushi Nemoto 
txx9_iocled_dir_out(struct gpio_chip * chip,unsigned int offset,int value)626ae027eadSAtsushi Nemoto static int txx9_iocled_dir_out(struct gpio_chip *chip, unsigned int offset,
627ae027eadSAtsushi Nemoto 			       int value)
628ae027eadSAtsushi Nemoto {
629ae027eadSAtsushi Nemoto 	txx9_iocled_set(chip, offset, value);
630ae027eadSAtsushi Nemoto 	return 0;
631ae027eadSAtsushi Nemoto }
632ae027eadSAtsushi Nemoto 
txx9_iocled_init(unsigned long baseaddr,int basenum,unsigned int num,int lowactive,const char * color,char ** deftriggers)633ae027eadSAtsushi Nemoto void __init txx9_iocled_init(unsigned long baseaddr,
634ae027eadSAtsushi Nemoto 			     int basenum, unsigned int num, int lowactive,
635ae027eadSAtsushi Nemoto 			     const char *color, char **deftriggers)
636ae027eadSAtsushi Nemoto {
637ae027eadSAtsushi Nemoto 	struct txx9_iocled_data *iocled;
638ae027eadSAtsushi Nemoto 	struct platform_device *pdev;
639ae027eadSAtsushi Nemoto 	int i;
640ae027eadSAtsushi Nemoto 	static char *default_triggers[] __initdata = {
641ae027eadSAtsushi Nemoto 		"heartbeat",
642dde00512SStephan Linz 		"disk-activity",
643ae027eadSAtsushi Nemoto 		"nand-disk",
644ae027eadSAtsushi Nemoto 		NULL,
645ae027eadSAtsushi Nemoto 	};
646ae027eadSAtsushi Nemoto 
647ae027eadSAtsushi Nemoto 	if (!deftriggers)
648ae027eadSAtsushi Nemoto 		deftriggers = default_triggers;
649ae027eadSAtsushi Nemoto 	iocled = kzalloc(sizeof(*iocled), GFP_KERNEL);
650ae027eadSAtsushi Nemoto 	if (!iocled)
651ae027eadSAtsushi Nemoto 		return;
652ae027eadSAtsushi Nemoto 	iocled->mmioaddr = ioremap(baseaddr, 1);
653ae027eadSAtsushi Nemoto 	if (!iocled->mmioaddr)
65470ebadc8SJulia Lawall 		goto out_free;
655ae027eadSAtsushi Nemoto 	iocled->chip.get = txx9_iocled_get;
656ae027eadSAtsushi Nemoto 	iocled->chip.set = txx9_iocled_set;
657ae027eadSAtsushi Nemoto 	iocled->chip.direction_input = txx9_iocled_dir_in;
658ae027eadSAtsushi Nemoto 	iocled->chip.direction_output = txx9_iocled_dir_out;
659ae027eadSAtsushi Nemoto 	iocled->chip.label = "iocled";
660ae027eadSAtsushi Nemoto 	iocled->chip.base = basenum;
661ae027eadSAtsushi Nemoto 	iocled->chip.ngpio = num;
662be7658f7SLinus Walleij 	if (gpiochip_add_data(&iocled->chip, iocled))
66370ebadc8SJulia Lawall 		goto out_unmap;
664ae027eadSAtsushi Nemoto 	if (basenum < 0)
665ae027eadSAtsushi Nemoto 		basenum = iocled->chip.base;
666ae027eadSAtsushi Nemoto 
667ae027eadSAtsushi Nemoto 	pdev = platform_device_alloc("leds-gpio", basenum);
668ae027eadSAtsushi Nemoto 	if (!pdev)
66970ebadc8SJulia Lawall 		goto out_gpio;
670ae027eadSAtsushi Nemoto 	iocled->pdata.num_leds = num;
671ae027eadSAtsushi Nemoto 	iocled->pdata.leds = iocled->leds;
672ae027eadSAtsushi Nemoto 	for (i = 0; i < num; i++) {
673ae027eadSAtsushi Nemoto 		struct gpio_led *led = &iocled->leds[i];
674ae027eadSAtsushi Nemoto 		snprintf(iocled->names[i], sizeof(iocled->names[i]),
675ae027eadSAtsushi Nemoto 			 "iocled:%s:%u", color, i);
676ae027eadSAtsushi Nemoto 		led->name = iocled->names[i];
677ae027eadSAtsushi Nemoto 		led->gpio = basenum + i;
678ae027eadSAtsushi Nemoto 		led->active_low = lowactive;
679ae027eadSAtsushi Nemoto 		if (deftriggers && *deftriggers)
680ae027eadSAtsushi Nemoto 			led->default_trigger = *deftriggers++;
681ae027eadSAtsushi Nemoto 	}
682ae027eadSAtsushi Nemoto 	pdev->dev.platform_data = &iocled->pdata;
683ae027eadSAtsushi Nemoto 	if (platform_device_add(pdev))
68470ebadc8SJulia Lawall 		goto out_pdev;
68570ebadc8SJulia Lawall 	return;
68688d5e520Sabdoulaye berthe 
68770ebadc8SJulia Lawall out_pdev:
688ae027eadSAtsushi Nemoto 	platform_device_put(pdev);
68970ebadc8SJulia Lawall out_gpio:
69088d5e520Sabdoulaye berthe 	gpiochip_remove(&iocled->chip);
69170ebadc8SJulia Lawall out_unmap:
69270ebadc8SJulia Lawall 	iounmap(iocled->mmioaddr);
69370ebadc8SJulia Lawall out_free:
69470ebadc8SJulia Lawall 	kfree(iocled);
695ae027eadSAtsushi Nemoto }
696ae027eadSAtsushi Nemoto #else /* CONFIG_LEDS_GPIO */
txx9_iocled_init(unsigned long baseaddr,int basenum,unsigned int num,int lowactive,const char * color,char ** deftriggers)697ae027eadSAtsushi Nemoto void __init txx9_iocled_init(unsigned long baseaddr,
698ae027eadSAtsushi Nemoto 			     int basenum, unsigned int num, int lowactive,
699ae027eadSAtsushi Nemoto 			     const char *color, char **deftriggers)
700ae027eadSAtsushi Nemoto {
701ae027eadSAtsushi Nemoto }
702ae027eadSAtsushi Nemoto #endif /* CONFIG_LEDS_GPIO */
703f48c8c95SAtsushi Nemoto 
txx9_dmac_init(int id,unsigned long baseaddr,int irq,const struct txx9dmac_platform_data * pdata)704f48c8c95SAtsushi Nemoto void __init txx9_dmac_init(int id, unsigned long baseaddr, int irq,
705f48c8c95SAtsushi Nemoto 			   const struct txx9dmac_platform_data *pdata)
706f48c8c95SAtsushi Nemoto {
707b33b4407SFlorian Fainelli #if IS_ENABLED(CONFIG_TXX9_DMAC)
708f48c8c95SAtsushi Nemoto 	struct resource res[] = {
709f48c8c95SAtsushi Nemoto 		{
710f48c8c95SAtsushi Nemoto 			.start = baseaddr,
711f48c8c95SAtsushi Nemoto 			.end = baseaddr + 0x800 - 1,
712f48c8c95SAtsushi Nemoto 			.flags = IORESOURCE_MEM,
713f48c8c95SAtsushi Nemoto #ifndef CONFIG_MACH_TX49XX
714f48c8c95SAtsushi Nemoto 		}, {
715f48c8c95SAtsushi Nemoto 			.start = irq,
716f48c8c95SAtsushi Nemoto 			.flags = IORESOURCE_IRQ,
717f48c8c95SAtsushi Nemoto #endif
718f48c8c95SAtsushi Nemoto 		}
719f48c8c95SAtsushi Nemoto 	};
720f48c8c95SAtsushi Nemoto #ifdef CONFIG_MACH_TX49XX
721f48c8c95SAtsushi Nemoto 	struct resource chan_res[] = {
722f48c8c95SAtsushi Nemoto 		{
723f48c8c95SAtsushi Nemoto 			.flags = IORESOURCE_IRQ,
724f48c8c95SAtsushi Nemoto 		}
725f48c8c95SAtsushi Nemoto 	};
726f48c8c95SAtsushi Nemoto #endif
727f48c8c95SAtsushi Nemoto 	struct platform_device *pdev = platform_device_alloc("txx9dmac", id);
728f48c8c95SAtsushi Nemoto 	struct txx9dmac_chan_platform_data cpdata;
729f48c8c95SAtsushi Nemoto 	int i;
730f48c8c95SAtsushi Nemoto 
731f48c8c95SAtsushi Nemoto 	if (!pdev ||
732f48c8c95SAtsushi Nemoto 	    platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) ||
733f48c8c95SAtsushi Nemoto 	    platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
734f48c8c95SAtsushi Nemoto 	    platform_device_add(pdev)) {
735f48c8c95SAtsushi Nemoto 		platform_device_put(pdev);
736f48c8c95SAtsushi Nemoto 		return;
737f48c8c95SAtsushi Nemoto 	}
738f48c8c95SAtsushi Nemoto 	memset(&cpdata, 0, sizeof(cpdata));
739f48c8c95SAtsushi Nemoto 	cpdata.dmac_dev = pdev;
740f48c8c95SAtsushi Nemoto 	for (i = 0; i < TXX9_DMA_MAX_NR_CHANNELS; i++) {
741f48c8c95SAtsushi Nemoto #ifdef CONFIG_MACH_TX49XX
742f48c8c95SAtsushi Nemoto 		chan_res[0].start = irq + i;
743f48c8c95SAtsushi Nemoto #endif
744f48c8c95SAtsushi Nemoto 		pdev = platform_device_alloc("txx9dmac-chan",
745f48c8c95SAtsushi Nemoto 					     id * TXX9_DMA_MAX_NR_CHANNELS + i);
746f48c8c95SAtsushi Nemoto 		if (!pdev ||
747f48c8c95SAtsushi Nemoto #ifdef CONFIG_MACH_TX49XX
748f48c8c95SAtsushi Nemoto 		    platform_device_add_resources(pdev, chan_res,
749f48c8c95SAtsushi Nemoto 						  ARRAY_SIZE(chan_res)) ||
750f48c8c95SAtsushi Nemoto #endif
751f48c8c95SAtsushi Nemoto 		    platform_device_add_data(pdev, &cpdata, sizeof(cpdata)) ||
752f48c8c95SAtsushi Nemoto 		    platform_device_add(pdev))
753f48c8c95SAtsushi Nemoto 			platform_device_put(pdev);
754f48c8c95SAtsushi Nemoto 	}
755f48c8c95SAtsushi Nemoto #endif
756f48c8c95SAtsushi Nemoto }
757742cd586SAtsushi Nemoto 
txx9_aclc_init(unsigned long baseaddr,int irq,unsigned int dmac_id,unsigned int dma_chan_out,unsigned int dma_chan_in)758742cd586SAtsushi Nemoto void __init txx9_aclc_init(unsigned long baseaddr, int irq,
759742cd586SAtsushi Nemoto 			   unsigned int dmac_id,
760742cd586SAtsushi Nemoto 			   unsigned int dma_chan_out,
761742cd586SAtsushi Nemoto 			   unsigned int dma_chan_in)
762742cd586SAtsushi Nemoto {
763742cd586SAtsushi Nemoto }
764c3b28ae2SAtsushi Nemoto 
765*1003a1adSRicardo B. Marliere static const struct bus_type txx9_sramc_subsys = {
766269a3eb1SKay Sievers 	.name = "txx9_sram",
767269a3eb1SKay Sievers 	.dev_name = "txx9_sram",
768269a3eb1SKay Sievers };
769c3b28ae2SAtsushi Nemoto 
770269a3eb1SKay Sievers struct txx9_sramc_dev {
771269a3eb1SKay Sievers 	struct device dev;
772c3b28ae2SAtsushi Nemoto 	struct bin_attribute bindata_attr;
773c3b28ae2SAtsushi Nemoto 	void __iomem *base;
774c3b28ae2SAtsushi Nemoto };
775c3b28ae2SAtsushi Nemoto 
txx9_sram_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t pos,size_t size)7762c3c8beaSChris Wright static ssize_t txx9_sram_read(struct file *filp, struct kobject *kobj,
777c3b28ae2SAtsushi Nemoto 			      struct bin_attribute *bin_attr,
778c3b28ae2SAtsushi Nemoto 			      char *buf, loff_t pos, size_t size)
779c3b28ae2SAtsushi Nemoto {
780269a3eb1SKay Sievers 	struct txx9_sramc_dev *dev = bin_attr->private;
781c3b28ae2SAtsushi Nemoto 	size_t ramsize = bin_attr->size;
782c3b28ae2SAtsushi Nemoto 
783c3b28ae2SAtsushi Nemoto 	if (pos >= ramsize)
784c3b28ae2SAtsushi Nemoto 		return 0;
785c3b28ae2SAtsushi Nemoto 	if (pos + size > ramsize)
786c3b28ae2SAtsushi Nemoto 		size = ramsize - pos;
787c3b28ae2SAtsushi Nemoto 	memcpy_fromio(buf, dev->base + pos, size);
788c3b28ae2SAtsushi Nemoto 	return size;
789c3b28ae2SAtsushi Nemoto }
790c3b28ae2SAtsushi Nemoto 
txx9_sram_write(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t pos,size_t size)7912c3c8beaSChris Wright static ssize_t txx9_sram_write(struct file *filp, struct kobject *kobj,
792c3b28ae2SAtsushi Nemoto 			       struct bin_attribute *bin_attr,
793c3b28ae2SAtsushi Nemoto 			       char *buf, loff_t pos, size_t size)
794c3b28ae2SAtsushi Nemoto {
795269a3eb1SKay Sievers 	struct txx9_sramc_dev *dev = bin_attr->private;
796c3b28ae2SAtsushi Nemoto 	size_t ramsize = bin_attr->size;
797c3b28ae2SAtsushi Nemoto 
798c3b28ae2SAtsushi Nemoto 	if (pos >= ramsize)
799c3b28ae2SAtsushi Nemoto 		return 0;
800c3b28ae2SAtsushi Nemoto 	if (pos + size > ramsize)
801c3b28ae2SAtsushi Nemoto 		size = ramsize - pos;
802c3b28ae2SAtsushi Nemoto 	memcpy_toio(dev->base + pos, buf, size);
803c3b28ae2SAtsushi Nemoto 	return size;
804c3b28ae2SAtsushi Nemoto }
805c3b28ae2SAtsushi Nemoto 
txx9_device_release(struct device * dev)8061610c8a8SLevente Kurusa static void txx9_device_release(struct device *dev)
8071610c8a8SLevente Kurusa {
8081610c8a8SLevente Kurusa 	struct txx9_sramc_dev *tdev;
8091610c8a8SLevente Kurusa 
8101610c8a8SLevente Kurusa 	tdev = container_of(dev, struct txx9_sramc_dev, dev);
8111610c8a8SLevente Kurusa 	kfree(tdev);
8121610c8a8SLevente Kurusa }
8131610c8a8SLevente Kurusa 
txx9_sramc_init(struct resource * r)814c3b28ae2SAtsushi Nemoto void __init txx9_sramc_init(struct resource *r)
815c3b28ae2SAtsushi Nemoto {
816269a3eb1SKay Sievers 	struct txx9_sramc_dev *dev;
817c3b28ae2SAtsushi Nemoto 	size_t size;
818c3b28ae2SAtsushi Nemoto 	int err;
819c3b28ae2SAtsushi Nemoto 
820269a3eb1SKay Sievers 	err = subsys_system_register(&txx9_sramc_subsys, NULL);
821269a3eb1SKay Sievers 	if (err)
822c3b28ae2SAtsushi Nemoto 		return;
823c3b28ae2SAtsushi Nemoto 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
824c3b28ae2SAtsushi Nemoto 	if (!dev)
825c3b28ae2SAtsushi Nemoto 		return;
826c3b28ae2SAtsushi Nemoto 	size = resource_size(r);
827c3b28ae2SAtsushi Nemoto 	dev->base = ioremap(r->start, size);
8281610c8a8SLevente Kurusa 	if (!dev->base) {
8291610c8a8SLevente Kurusa 		kfree(dev);
8301610c8a8SLevente Kurusa 		return;
8311610c8a8SLevente Kurusa 	}
8321610c8a8SLevente Kurusa 	dev->dev.release = &txx9_device_release;
833269a3eb1SKay Sievers 	dev->dev.bus = &txx9_sramc_subsys;
834f937331bSWolfram Sang 	sysfs_bin_attr_init(&dev->bindata_attr);
835c3b28ae2SAtsushi Nemoto 	dev->bindata_attr.attr.name = "bindata";
836c3b28ae2SAtsushi Nemoto 	dev->bindata_attr.attr.mode = S_IRUSR | S_IWUSR;
837c3b28ae2SAtsushi Nemoto 	dev->bindata_attr.read = txx9_sram_read;
838c3b28ae2SAtsushi Nemoto 	dev->bindata_attr.write = txx9_sram_write;
839c3b28ae2SAtsushi Nemoto 	dev->bindata_attr.size = size;
840c3b28ae2SAtsushi Nemoto 	dev->bindata_attr.private = dev;
841269a3eb1SKay Sievers 	err = device_register(&dev->dev);
842c3b28ae2SAtsushi Nemoto 	if (err)
8431610c8a8SLevente Kurusa 		goto exit_put;
844c3b28ae2SAtsushi Nemoto 	err = sysfs_create_bin_file(&dev->dev.kobj, &dev->bindata_attr);
845c3b28ae2SAtsushi Nemoto 	if (err) {
846c3b28ae2SAtsushi Nemoto 		iounmap(dev->base);
847c6e1241aSDing Xiang 		device_unregister(&dev->dev);
848c3b28ae2SAtsushi Nemoto 	}
8491610c8a8SLevente Kurusa 	return;
8501610c8a8SLevente Kurusa exit_put:
851c6e1241aSDing Xiang 	iounmap(dev->base);
8521610c8a8SLevente Kurusa 	put_device(&dev->dev);
853c3b28ae2SAtsushi Nemoto }
854