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