1/*
2 * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
3 *	    and RBTX49xx patch from CELF patch archive.
4 *
5 * 2003-2005 (c) MontaVista Software, Inc.
6 * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License.  See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/interrupt.h>
16#include <linux/string.h>
17#include <linux/module.h>
18#include <linux/clk.h>
19#include <linux/err.h>
20#include <linux/gpio.h>
21#include <linux/platform_device.h>
22#include <linux/serial_core.h>
23#include <linux/mtd/physmap.h>
24#include <linux/leds.h>
25#include <linux/device.h>
26#include <linux/slab.h>
27#include <linux/irq.h>
28#include <asm/bootinfo.h>
29#include <asm/idle.h>
30#include <asm/time.h>
31#include <asm/reboot.h>
32#include <asm/r4kcache.h>
33#include <asm/sections.h>
34#include <asm/txx9/generic.h>
35#include <asm/txx9/pci.h>
36#include <asm/txx9tmr.h>
37#include <asm/txx9/ndfmc.h>
38#include <asm/txx9/dmac.h>
39#ifdef CONFIG_CPU_TX49XX
40#include <asm/txx9/tx4938.h>
41#endif
42
43/* EBUSC settings of TX4927, etc. */
44struct resource txx9_ce_res[8];
45static char txx9_ce_res_name[8][4];	/* "CEn" */
46
47/* pcode, internal register */
48unsigned int txx9_pcode;
49char txx9_pcode_str[8];
50static struct resource txx9_reg_res = {
51	.name = txx9_pcode_str,
52	.flags = IORESOURCE_MEM,
53};
54void __init
55txx9_reg_res_init(unsigned int pcode, unsigned long base, unsigned long size)
56{
57	int i;
58
59	for (i = 0; i < ARRAY_SIZE(txx9_ce_res); i++) {
60		sprintf(txx9_ce_res_name[i], "CE%d", i);
61		txx9_ce_res[i].flags = IORESOURCE_MEM;
62		txx9_ce_res[i].name = txx9_ce_res_name[i];
63	}
64
65	txx9_pcode = pcode;
66	sprintf(txx9_pcode_str, "TX%x", pcode);
67	if (base) {
68		txx9_reg_res.start = base & 0xfffffffffULL;
69		txx9_reg_res.end = (base & 0xfffffffffULL) + (size - 1);
70		request_resource(&iomem_resource, &txx9_reg_res);
71	}
72}
73
74/* clocks */
75unsigned int txx9_master_clock;
76unsigned int txx9_cpu_clock;
77unsigned int txx9_gbus_clock;
78
79#ifdef CONFIG_CPU_TX39XX
80/* don't enable by default - see errata */
81int txx9_ccfg_toeon __initdata;
82#else
83int txx9_ccfg_toeon __initdata = 1;
84#endif
85
86/* Minimum CLK support */
87
88struct clk *clk_get(struct device *dev, const char *id)
89{
90	if (!strcmp(id, "spi-baseclk"))
91		return (struct clk *)((unsigned long)txx9_gbus_clock / 2 / 2);
92	if (!strcmp(id, "imbus_clk"))
93		return (struct clk *)((unsigned long)txx9_gbus_clock / 2);
94	return ERR_PTR(-ENOENT);
95}
96EXPORT_SYMBOL(clk_get);
97
98int clk_enable(struct clk *clk)
99{
100	return 0;
101}
102EXPORT_SYMBOL(clk_enable);
103
104void clk_disable(struct clk *clk)
105{
106}
107EXPORT_SYMBOL(clk_disable);
108
109unsigned long clk_get_rate(struct clk *clk)
110{
111	return (unsigned long)clk;
112}
113EXPORT_SYMBOL(clk_get_rate);
114
115void clk_put(struct clk *clk)
116{
117}
118EXPORT_SYMBOL(clk_put);
119
120/* GPIO support */
121
122#ifdef CONFIG_GPIOLIB
123int gpio_to_irq(unsigned gpio)
124{
125	return -EINVAL;
126}
127EXPORT_SYMBOL(gpio_to_irq);
128
129int irq_to_gpio(unsigned irq)
130{
131	return -EINVAL;
132}
133EXPORT_SYMBOL(irq_to_gpio);
134#endif
135
136#define BOARD_VEC(board)	extern struct txx9_board_vec board;
137#include <asm/txx9/boards.h>
138#undef BOARD_VEC
139
140struct txx9_board_vec *txx9_board_vec __initdata;
141static char txx9_system_type[32];
142
143static struct txx9_board_vec *board_vecs[] __initdata = {
144#define BOARD_VEC(board)	&board,
145#include <asm/txx9/boards.h>
146#undef BOARD_VEC
147};
148
149static struct txx9_board_vec *__init find_board_byname(const char *name)
150{
151	int i;
152
153	/* search board_vecs table */
154	for (i = 0; i < ARRAY_SIZE(board_vecs); i++) {
155		if (strstr(board_vecs[i]->system, name))
156			return board_vecs[i];
157	}
158	return NULL;
159}
160
161static void __init prom_init_cmdline(void)
162{
163	int argc;
164	int *argv32;
165	int i;			/* Always ignore the "-c" at argv[0] */
166
167	if (fw_arg0 >= CKSEG0 || fw_arg1 < CKSEG0) {
168		/*
169		 * argc is not a valid number, or argv32 is not a valid
170		 * pointer
171		 */
172		argc = 0;
173		argv32 = NULL;
174	} else {
175		argc = (int)fw_arg0;
176		argv32 = (int *)fw_arg1;
177	}
178
179	arcs_cmdline[0] = '\0';
180
181	for (i = 1; i < argc; i++) {
182		char *str = (char *)(long)argv32[i];
183		if (i != 1)
184			strcat(arcs_cmdline, " ");
185		if (strchr(str, ' ')) {
186			strcat(arcs_cmdline, "\"");
187			strcat(arcs_cmdline, str);
188			strcat(arcs_cmdline, "\"");
189		} else
190			strcat(arcs_cmdline, str);
191	}
192}
193
194static int txx9_ic_disable __initdata;
195static int txx9_dc_disable __initdata;
196
197#if defined(CONFIG_CPU_TX49XX)
198/* flush all cache on very early stage (before 4k_cache_init) */
199static void __init early_flush_dcache(void)
200{
201	unsigned int conf = read_c0_config();
202	unsigned int dc_size = 1 << (12 + ((conf & CONF_DC) >> 6));
203	unsigned int linesz = 32;
204	unsigned long addr, end;
205
206	end = INDEX_BASE + dc_size / 4;
207	/* 4way, waybit=0 */
208	for (addr = INDEX_BASE; addr < end; addr += linesz) {
209		cache_op(Index_Writeback_Inv_D, addr | 0);
210		cache_op(Index_Writeback_Inv_D, addr | 1);
211		cache_op(Index_Writeback_Inv_D, addr | 2);
212		cache_op(Index_Writeback_Inv_D, addr | 3);
213	}
214}
215
216static void __init txx9_cache_fixup(void)
217{
218	unsigned int conf;
219
220	conf = read_c0_config();
221	/* flush and disable */
222	if (txx9_ic_disable) {
223		conf |= TX49_CONF_IC;
224		write_c0_config(conf);
225	}
226	if (txx9_dc_disable) {
227		early_flush_dcache();
228		conf |= TX49_CONF_DC;
229		write_c0_config(conf);
230	}
231
232	/* enable cache */
233	conf = read_c0_config();
234	if (!txx9_ic_disable)
235		conf &= ~TX49_CONF_IC;
236	if (!txx9_dc_disable)
237		conf &= ~TX49_CONF_DC;
238	write_c0_config(conf);
239
240	if (conf & TX49_CONF_IC)
241		pr_info("TX49XX I-Cache disabled.\n");
242	if (conf & TX49_CONF_DC)
243		pr_info("TX49XX D-Cache disabled.\n");
244}
245#elif defined(CONFIG_CPU_TX39XX)
246/* flush all cache on very early stage (before tx39_cache_init) */
247static void __init early_flush_dcache(void)
248{
249	unsigned int conf = read_c0_config();
250	unsigned int dc_size = 1 << (10 + ((conf & TX39_CONF_DCS_MASK) >>
251					   TX39_CONF_DCS_SHIFT));
252	unsigned int linesz = 16;
253	unsigned long addr, end;
254
255	end = INDEX_BASE + dc_size / 2;
256	/* 2way, waybit=0 */
257	for (addr = INDEX_BASE; addr < end; addr += linesz) {
258		cache_op(Index_Writeback_Inv_D, addr | 0);
259		cache_op(Index_Writeback_Inv_D, addr | 1);
260	}
261}
262
263static void __init txx9_cache_fixup(void)
264{
265	unsigned int conf;
266
267	conf = read_c0_config();
268	/* flush and disable */
269	if (txx9_ic_disable) {
270		conf &= ~TX39_CONF_ICE;
271		write_c0_config(conf);
272	}
273	if (txx9_dc_disable) {
274		early_flush_dcache();
275		conf &= ~TX39_CONF_DCE;
276		write_c0_config(conf);
277	}
278
279	/* enable cache */
280	conf = read_c0_config();
281	if (!txx9_ic_disable)
282		conf |= TX39_CONF_ICE;
283	if (!txx9_dc_disable)
284		conf |= TX39_CONF_DCE;
285	write_c0_config(conf);
286
287	if (!(conf & TX39_CONF_ICE))
288		pr_info("TX39XX I-Cache disabled.\n");
289	if (!(conf & TX39_CONF_DCE))
290		pr_info("TX39XX D-Cache disabled.\n");
291}
292#else
293static inline void txx9_cache_fixup(void)
294{
295}
296#endif
297
298static void __init preprocess_cmdline(void)
299{
300	static char cmdline[COMMAND_LINE_SIZE] __initdata;
301	char *s;
302
303	strcpy(cmdline, arcs_cmdline);
304	s = cmdline;
305	arcs_cmdline[0] = '\0';
306	while (s && *s) {
307		char *str = strsep(&s, " ");
308		if (strncmp(str, "board=", 6) == 0) {
309			txx9_board_vec = find_board_byname(str + 6);
310			continue;
311		} else if (strncmp(str, "masterclk=", 10) == 0) {
312			unsigned int val;
313			if (kstrtouint(str + 10, 10, &val) == 0)
314				txx9_master_clock = val;
315			continue;
316		} else if (strcmp(str, "icdisable") == 0) {
317			txx9_ic_disable = 1;
318			continue;
319		} else if (strcmp(str, "dcdisable") == 0) {
320			txx9_dc_disable = 1;
321			continue;
322		} else if (strcmp(str, "toeoff") == 0) {
323			txx9_ccfg_toeon = 0;
324			continue;
325		} else if (strcmp(str, "toeon") == 0) {
326			txx9_ccfg_toeon = 1;
327			continue;
328		}
329		if (arcs_cmdline[0])
330			strcat(arcs_cmdline, " ");
331		strcat(arcs_cmdline, str);
332	}
333
334	txx9_cache_fixup();
335}
336
337static void __init select_board(void)
338{
339	const char *envstr;
340
341	/* first, determine by "board=" argument in preprocess_cmdline() */
342	if (txx9_board_vec)
343		return;
344	/* next, determine by "board" envvar */
345	envstr = prom_getenv("board");
346	if (envstr) {
347		txx9_board_vec = find_board_byname(envstr);
348		if (txx9_board_vec)
349			return;
350	}
351
352	/* select "default" board */
353#ifdef CONFIG_TOSHIBA_JMR3927
354	txx9_board_vec = &jmr3927_vec;
355#endif
356#ifdef CONFIG_CPU_TX49XX
357	switch (TX4938_REV_PCODE()) {
358#ifdef CONFIG_TOSHIBA_RBTX4927
359	case 0x4927:
360		txx9_board_vec = &rbtx4927_vec;
361		break;
362	case 0x4937:
363		txx9_board_vec = &rbtx4937_vec;
364		break;
365#endif
366#ifdef CONFIG_TOSHIBA_RBTX4938
367	case 0x4938:
368		txx9_board_vec = &rbtx4938_vec;
369		break;
370#endif
371#ifdef CONFIG_TOSHIBA_RBTX4939
372	case 0x4939:
373		txx9_board_vec = &rbtx4939_vec;
374		break;
375#endif
376	}
377#endif
378}
379
380void __init prom_init(void)
381{
382	prom_init_cmdline();
383	preprocess_cmdline();
384	select_board();
385
386	strcpy(txx9_system_type, txx9_board_vec->system);
387
388	txx9_board_vec->prom_init();
389}
390
391void __init prom_free_prom_memory(void)
392{
393	unsigned long saddr = PAGE_SIZE;
394	unsigned long eaddr = __pa_symbol(&_text);
395
396	if (saddr < eaddr)
397		free_init_pages("prom memory", saddr, eaddr);
398}
399
400const char *get_system_type(void)
401{
402	return txx9_system_type;
403}
404
405const char *__init prom_getenv(const char *name)
406{
407	const s32 *str;
408
409	if (fw_arg2 < CKSEG0)
410		return NULL;
411
412	str = (const s32 *)fw_arg2;
413	/* YAMON style ("name", "value" pairs) */
414	while (str[0] && str[1]) {
415		if (!strcmp((const char *)(unsigned long)str[0], name))
416			return (const char *)(unsigned long)str[1];
417		str += 2;
418	}
419	return NULL;
420}
421
422static void __noreturn txx9_machine_halt(void)
423{
424	local_irq_disable();
425	clear_c0_status(ST0_IM);
426	while (1) {
427		if (cpu_wait) {
428			(*cpu_wait)();
429			if (cpu_has_counter) {
430				/*
431				 * Clear counter interrupt while it
432				 * breaks WAIT instruction even if
433				 * masked.
434				 */
435				write_c0_compare(0);
436			}
437		}
438	}
439}
440
441/* Watchdog support */
442void __init txx9_wdt_init(unsigned long base)
443{
444	struct resource res = {
445		.start	= base,
446		.end	= base + 0x100 - 1,
447		.flags	= IORESOURCE_MEM,
448	};
449	platform_device_register_simple("txx9wdt", -1, &res, 1);
450}
451
452void txx9_wdt_now(unsigned long base)
453{
454	struct txx9_tmr_reg __iomem *tmrptr =
455		ioremap(base, sizeof(struct txx9_tmr_reg));
456	/* disable watch dog timer */
457	__raw_writel(TXx9_TMWTMR_WDIS | TXx9_TMWTMR_TWC, &tmrptr->wtmr);
458	__raw_writel(0, &tmrptr->tcr);
459	/* kick watchdog */
460	__raw_writel(TXx9_TMWTMR_TWIE, &tmrptr->wtmr);
461	__raw_writel(1, &tmrptr->cpra); /* immediate */
462	__raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG,
463		     &tmrptr->tcr);
464}
465
466/* SPI support */
467void __init txx9_spi_init(int busid, unsigned long base, int irq)
468{
469	struct resource res[] = {
470		{
471			.start	= base,
472			.end	= base + 0x20 - 1,
473			.flags	= IORESOURCE_MEM,
474		}, {
475			.start	= irq,
476			.flags	= IORESOURCE_IRQ,
477		},
478	};
479	platform_device_register_simple("spi_txx9", busid,
480					res, ARRAY_SIZE(res));
481}
482
483void __init txx9_ethaddr_init(unsigned int id, unsigned char *ethaddr)
484{
485	struct platform_device *pdev =
486		platform_device_alloc("tc35815-mac", id);
487	if (!pdev ||
488	    platform_device_add_data(pdev, ethaddr, 6) ||
489	    platform_device_add(pdev))
490		platform_device_put(pdev);
491}
492
493void __init txx9_sio_init(unsigned long baseaddr, int irq,
494			  unsigned int line, unsigned int sclk, int nocts)
495{
496#ifdef CONFIG_SERIAL_TXX9
497	struct uart_port req;
498
499	memset(&req, 0, sizeof(req));
500	req.line = line;
501	req.iotype = UPIO_MEM;
502	req.membase = ioremap(baseaddr, 0x24);
503	req.mapbase = baseaddr;
504	req.irq = irq;
505	if (!nocts)
506		req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
507	if (sclk) {
508		req.flags |= UPF_MAGIC_MULTIPLIER /*USE_SCLK*/;
509		req.uartclk = sclk;
510	} else
511		req.uartclk = TXX9_IMCLK;
512	early_serial_txx9_setup(&req);
513#endif /* CONFIG_SERIAL_TXX9 */
514}
515
516#ifdef CONFIG_EARLY_PRINTK
517static void null_prom_putchar(char c)
518{
519}
520void (*txx9_prom_putchar)(char c) = null_prom_putchar;
521
522void prom_putchar(char c)
523{
524	txx9_prom_putchar(c);
525}
526
527static void __iomem *early_txx9_sio_port;
528
529static void early_txx9_sio_putchar(char c)
530{
531#define TXX9_SICISR	0x0c
532#define TXX9_SITFIFO	0x1c
533#define TXX9_SICISR_TXALS	0x00000002
534	while (!(__raw_readl(early_txx9_sio_port + TXX9_SICISR) &
535		 TXX9_SICISR_TXALS))
536		;
537	__raw_writel(c, early_txx9_sio_port + TXX9_SITFIFO);
538}
539
540void __init txx9_sio_putchar_init(unsigned long baseaddr)
541{
542	early_txx9_sio_port = ioremap(baseaddr, 0x24);
543	txx9_prom_putchar = early_txx9_sio_putchar;
544}
545#endif /* CONFIG_EARLY_PRINTK */
546
547/* wrappers */
548void __init plat_mem_setup(void)
549{
550	ioport_resource.start = 0;
551	ioport_resource.end = ~0UL;	/* no limit */
552	iomem_resource.start = 0;
553	iomem_resource.end = ~0UL;	/* no limit */
554
555	/* fallback restart/halt routines */
556	_machine_restart = (void (*)(char *))txx9_machine_halt;
557	_machine_halt = txx9_machine_halt;
558	pm_power_off = txx9_machine_halt;
559
560#ifdef CONFIG_PCI
561	pcibios_plat_setup = txx9_pcibios_setup;
562#endif
563	txx9_board_vec->mem_setup();
564}
565
566void __init arch_init_irq(void)
567{
568	txx9_board_vec->irq_setup();
569}
570
571void __init plat_time_init(void)
572{
573#ifdef CONFIG_CPU_TX49XX
574	mips_hpt_frequency = txx9_cpu_clock / 2;
575#endif
576	txx9_board_vec->time_init();
577}
578
579static int __init _txx9_arch_init(void)
580{
581	if (txx9_board_vec->arch_init)
582		txx9_board_vec->arch_init();
583	return 0;
584}
585arch_initcall(_txx9_arch_init);
586
587static int __init _txx9_device_init(void)
588{
589	if (txx9_board_vec->device_init)
590		txx9_board_vec->device_init();
591	return 0;
592}
593device_initcall(_txx9_device_init);
594
595int (*txx9_irq_dispatch)(int pending);
596asmlinkage void plat_irq_dispatch(void)
597{
598	int pending = read_c0_status() & read_c0_cause() & ST0_IM;
599	int irq = txx9_irq_dispatch(pending);
600
601	if (likely(irq >= 0))
602		do_IRQ(irq);
603	else
604		spurious_interrupt();
605}
606
607/* see include/asm-mips/mach-tx39xx/mangle-port.h, for example. */
608#ifdef NEEDS_TXX9_SWIZZLE_ADDR_B
609static unsigned long __swizzle_addr_none(unsigned long port)
610{
611	return port;
612}
613unsigned long (*__swizzle_addr_b)(unsigned long port) = __swizzle_addr_none;
614EXPORT_SYMBOL(__swizzle_addr_b);
615#endif
616
617#ifdef NEEDS_TXX9_IOSWABW
618static u16 ioswabw_default(volatile u16 *a, u16 x)
619{
620	return le16_to_cpu(x);
621}
622static u16 __mem_ioswabw_default(volatile u16 *a, u16 x)
623{
624	return x;
625}
626u16 (*ioswabw)(volatile u16 *a, u16 x) = ioswabw_default;
627EXPORT_SYMBOL(ioswabw);
628u16 (*__mem_ioswabw)(volatile u16 *a, u16 x) = __mem_ioswabw_default;
629EXPORT_SYMBOL(__mem_ioswabw);
630#endif
631
632void __init txx9_physmap_flash_init(int no, unsigned long addr,
633				    unsigned long size,
634				    const struct physmap_flash_data *pdata)
635{
636#if IS_ENABLED(CONFIG_MTD_PHYSMAP)
637	struct resource res = {
638		.start = addr,
639		.end = addr + size - 1,
640		.flags = IORESOURCE_MEM,
641	};
642	struct platform_device *pdev;
643	static struct mtd_partition parts[2];
644	struct physmap_flash_data pdata_part;
645
646	/* If this area contained boot area, make separate partition */
647	if (pdata->nr_parts == 0 && !pdata->parts &&
648	    addr < 0x1fc00000 && addr + size > 0x1fc00000 &&
649	    !parts[0].name) {
650		parts[0].name = "boot";
651		parts[0].offset = 0x1fc00000 - addr;
652		parts[0].size = addr + size - 0x1fc00000;
653		parts[1].name = "user";
654		parts[1].offset = 0;
655		parts[1].size = 0x1fc00000 - addr;
656		pdata_part = *pdata;
657		pdata_part.nr_parts = ARRAY_SIZE(parts);
658		pdata_part.parts = parts;
659		pdata = &pdata_part;
660	}
661
662	pdev = platform_device_alloc("physmap-flash", no);
663	if (!pdev ||
664	    platform_device_add_resources(pdev, &res, 1) ||
665	    platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
666	    platform_device_add(pdev))
667		platform_device_put(pdev);
668#endif
669}
670
671void __init txx9_ndfmc_init(unsigned long baseaddr,
672			    const struct txx9ndfmc_platform_data *pdata)
673{
674#if IS_ENABLED(CONFIG_MTD_NAND_TXX9NDFMC)
675	struct resource res = {
676		.start = baseaddr,
677		.end = baseaddr + 0x1000 - 1,
678		.flags = IORESOURCE_MEM,
679	};
680	struct platform_device *pdev = platform_device_alloc("txx9ndfmc", -1);
681
682	if (!pdev ||
683	    platform_device_add_resources(pdev, &res, 1) ||
684	    platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
685	    platform_device_add(pdev))
686		platform_device_put(pdev);
687#endif
688}
689
690#if IS_ENABLED(CONFIG_LEDS_GPIO)
691static DEFINE_SPINLOCK(txx9_iocled_lock);
692
693#define TXX9_IOCLED_MAXLEDS 8
694
695struct txx9_iocled_data {
696	struct gpio_chip chip;
697	u8 cur_val;
698	void __iomem *mmioaddr;
699	struct gpio_led_platform_data pdata;
700	struct gpio_led leds[TXX9_IOCLED_MAXLEDS];
701	char names[TXX9_IOCLED_MAXLEDS][32];
702};
703
704static int txx9_iocled_get(struct gpio_chip *chip, unsigned int offset)
705{
706	struct txx9_iocled_data *data =
707		container_of(chip, struct txx9_iocled_data, chip);
708	return data->cur_val & (1 << offset);
709}
710
711static void txx9_iocled_set(struct gpio_chip *chip, unsigned int offset,
712			    int value)
713{
714	struct txx9_iocled_data *data =
715		container_of(chip, struct txx9_iocled_data, chip);
716	unsigned long flags;
717	spin_lock_irqsave(&txx9_iocled_lock, flags);
718	if (value)
719		data->cur_val |= 1 << offset;
720	else
721		data->cur_val &= ~(1 << offset);
722	writeb(data->cur_val, data->mmioaddr);
723	mmiowb();
724	spin_unlock_irqrestore(&txx9_iocled_lock, flags);
725}
726
727static int txx9_iocled_dir_in(struct gpio_chip *chip, unsigned int offset)
728{
729	return 0;
730}
731
732static int txx9_iocled_dir_out(struct gpio_chip *chip, unsigned int offset,
733			       int value)
734{
735	txx9_iocled_set(chip, offset, value);
736	return 0;
737}
738
739void __init txx9_iocled_init(unsigned long baseaddr,
740			     int basenum, unsigned int num, int lowactive,
741			     const char *color, char **deftriggers)
742{
743	struct txx9_iocled_data *iocled;
744	struct platform_device *pdev;
745	int i;
746	static char *default_triggers[] __initdata = {
747		"heartbeat",
748		"ide-disk",
749		"nand-disk",
750		NULL,
751	};
752
753	if (!deftriggers)
754		deftriggers = default_triggers;
755	iocled = kzalloc(sizeof(*iocled), GFP_KERNEL);
756	if (!iocled)
757		return;
758	iocled->mmioaddr = ioremap(baseaddr, 1);
759	if (!iocled->mmioaddr)
760		goto out_free;
761	iocled->chip.get = txx9_iocled_get;
762	iocled->chip.set = txx9_iocled_set;
763	iocled->chip.direction_input = txx9_iocled_dir_in;
764	iocled->chip.direction_output = txx9_iocled_dir_out;
765	iocled->chip.label = "iocled";
766	iocled->chip.base = basenum;
767	iocled->chip.ngpio = num;
768	if (gpiochip_add(&iocled->chip))
769		goto out_unmap;
770	if (basenum < 0)
771		basenum = iocled->chip.base;
772
773	pdev = platform_device_alloc("leds-gpio", basenum);
774	if (!pdev)
775		goto out_gpio;
776	iocled->pdata.num_leds = num;
777	iocled->pdata.leds = iocled->leds;
778	for (i = 0; i < num; i++) {
779		struct gpio_led *led = &iocled->leds[i];
780		snprintf(iocled->names[i], sizeof(iocled->names[i]),
781			 "iocled:%s:%u", color, i);
782		led->name = iocled->names[i];
783		led->gpio = basenum + i;
784		led->active_low = lowactive;
785		if (deftriggers && *deftriggers)
786			led->default_trigger = *deftriggers++;
787	}
788	pdev->dev.platform_data = &iocled->pdata;
789	if (platform_device_add(pdev))
790		goto out_pdev;
791	return;
792
793out_pdev:
794	platform_device_put(pdev);
795out_gpio:
796	gpiochip_remove(&iocled->chip);
797out_unmap:
798	iounmap(iocled->mmioaddr);
799out_free:
800	kfree(iocled);
801}
802#else /* CONFIG_LEDS_GPIO */
803void __init txx9_iocled_init(unsigned long baseaddr,
804			     int basenum, unsigned int num, int lowactive,
805			     const char *color, char **deftriggers)
806{
807}
808#endif /* CONFIG_LEDS_GPIO */
809
810void __init txx9_dmac_init(int id, unsigned long baseaddr, int irq,
811			   const struct txx9dmac_platform_data *pdata)
812{
813#if IS_ENABLED(CONFIG_TXX9_DMAC)
814	struct resource res[] = {
815		{
816			.start = baseaddr,
817			.end = baseaddr + 0x800 - 1,
818			.flags = IORESOURCE_MEM,
819#ifndef CONFIG_MACH_TX49XX
820		}, {
821			.start = irq,
822			.flags = IORESOURCE_IRQ,
823#endif
824		}
825	};
826#ifdef CONFIG_MACH_TX49XX
827	struct resource chan_res[] = {
828		{
829			.flags = IORESOURCE_IRQ,
830		}
831	};
832#endif
833	struct platform_device *pdev = platform_device_alloc("txx9dmac", id);
834	struct txx9dmac_chan_platform_data cpdata;
835	int i;
836
837	if (!pdev ||
838	    platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) ||
839	    platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
840	    platform_device_add(pdev)) {
841		platform_device_put(pdev);
842		return;
843	}
844	memset(&cpdata, 0, sizeof(cpdata));
845	cpdata.dmac_dev = pdev;
846	for (i = 0; i < TXX9_DMA_MAX_NR_CHANNELS; i++) {
847#ifdef CONFIG_MACH_TX49XX
848		chan_res[0].start = irq + i;
849#endif
850		pdev = platform_device_alloc("txx9dmac-chan",
851					     id * TXX9_DMA_MAX_NR_CHANNELS + i);
852		if (!pdev ||
853#ifdef CONFIG_MACH_TX49XX
854		    platform_device_add_resources(pdev, chan_res,
855						  ARRAY_SIZE(chan_res)) ||
856#endif
857		    platform_device_add_data(pdev, &cpdata, sizeof(cpdata)) ||
858		    platform_device_add(pdev))
859			platform_device_put(pdev);
860	}
861#endif
862}
863
864void __init txx9_aclc_init(unsigned long baseaddr, int irq,
865			   unsigned int dmac_id,
866			   unsigned int dma_chan_out,
867			   unsigned int dma_chan_in)
868{
869#if IS_ENABLED(CONFIG_SND_SOC_TXX9ACLC)
870	unsigned int dma_base = dmac_id * TXX9_DMA_MAX_NR_CHANNELS;
871	struct resource res[] = {
872		{
873			.start = baseaddr,
874			.end = baseaddr + 0x100 - 1,
875			.flags = IORESOURCE_MEM,
876		}, {
877			.start = irq,
878			.flags = IORESOURCE_IRQ,
879		}, {
880			.name = "txx9dmac-chan",
881			.start = dma_base + dma_chan_out,
882			.flags = IORESOURCE_DMA,
883		}, {
884			.name = "txx9dmac-chan",
885			.start = dma_base + dma_chan_in,
886			.flags = IORESOURCE_DMA,
887		}
888	};
889	struct platform_device *pdev =
890		platform_device_alloc("txx9aclc-ac97", -1);
891
892	if (!pdev ||
893	    platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) ||
894	    platform_device_add(pdev))
895		platform_device_put(pdev);
896#endif
897}
898
899static struct bus_type txx9_sramc_subsys = {
900	.name = "txx9_sram",
901	.dev_name = "txx9_sram",
902};
903
904struct txx9_sramc_dev {
905	struct device dev;
906	struct bin_attribute bindata_attr;
907	void __iomem *base;
908};
909
910static ssize_t txx9_sram_read(struct file *filp, struct kobject *kobj,
911			      struct bin_attribute *bin_attr,
912			      char *buf, loff_t pos, size_t size)
913{
914	struct txx9_sramc_dev *dev = bin_attr->private;
915	size_t ramsize = bin_attr->size;
916
917	if (pos >= ramsize)
918		return 0;
919	if (pos + size > ramsize)
920		size = ramsize - pos;
921	memcpy_fromio(buf, dev->base + pos, size);
922	return size;
923}
924
925static ssize_t txx9_sram_write(struct file *filp, struct kobject *kobj,
926			       struct bin_attribute *bin_attr,
927			       char *buf, loff_t pos, size_t size)
928{
929	struct txx9_sramc_dev *dev = bin_attr->private;
930	size_t ramsize = bin_attr->size;
931
932	if (pos >= ramsize)
933		return 0;
934	if (pos + size > ramsize)
935		size = ramsize - pos;
936	memcpy_toio(dev->base + pos, buf, size);
937	return size;
938}
939
940static void txx9_device_release(struct device *dev)
941{
942	struct txx9_sramc_dev *tdev;
943
944	tdev = container_of(dev, struct txx9_sramc_dev, dev);
945	kfree(tdev);
946}
947
948void __init txx9_sramc_init(struct resource *r)
949{
950	struct txx9_sramc_dev *dev;
951	size_t size;
952	int err;
953
954	err = subsys_system_register(&txx9_sramc_subsys, NULL);
955	if (err)
956		return;
957	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
958	if (!dev)
959		return;
960	size = resource_size(r);
961	dev->base = ioremap(r->start, size);
962	if (!dev->base) {
963		kfree(dev);
964		return;
965	}
966	dev->dev.release = &txx9_device_release;
967	dev->dev.bus = &txx9_sramc_subsys;
968	sysfs_bin_attr_init(&dev->bindata_attr);
969	dev->bindata_attr.attr.name = "bindata";
970	dev->bindata_attr.attr.mode = S_IRUSR | S_IWUSR;
971	dev->bindata_attr.read = txx9_sram_read;
972	dev->bindata_attr.write = txx9_sram_write;
973	dev->bindata_attr.size = size;
974	dev->bindata_attr.private = dev;
975	err = device_register(&dev->dev);
976	if (err)
977		goto exit_put;
978	err = sysfs_create_bin_file(&dev->dev.kobj, &dev->bindata_attr);
979	if (err) {
980		device_unregister(&dev->dev);
981		iounmap(dev->base);
982		kfree(dev);
983	}
984	return;
985exit_put:
986	put_device(&dev->dev);
987	return;
988}
989