cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

udbg_scc.c (3942B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * udbg for zilog scc ports as found on Apple PowerMacs
      4 *
      5 * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
      6 */
      7#include <linux/types.h>
      8#include <linux/of.h>
      9#include <asm/udbg.h>
     10#include <asm/processor.h>
     11#include <asm/io.h>
     12#include <asm/pmac_feature.h>
     13
     14extern u8 real_readb(volatile u8 __iomem  *addr);
     15extern void real_writeb(u8 data, volatile u8 __iomem *addr);
     16
     17#define	SCC_TXRDY	4
     18#define SCC_RXRDY	1
     19
     20static volatile u8 __iomem *sccc;
     21static volatile u8 __iomem *sccd;
     22
     23static void udbg_scc_putc(char c)
     24{
     25	if (sccc) {
     26		while ((in_8(sccc) & SCC_TXRDY) == 0)
     27			;
     28		out_8(sccd,  c);
     29		if (c == '\n')
     30			udbg_scc_putc('\r');
     31	}
     32}
     33
     34static int udbg_scc_getc_poll(void)
     35{
     36	if (sccc) {
     37		if ((in_8(sccc) & SCC_RXRDY) != 0)
     38			return in_8(sccd);
     39		else
     40			return -1;
     41	}
     42	return -1;
     43}
     44
     45static int udbg_scc_getc(void)
     46{
     47	if (sccc) {
     48		while ((in_8(sccc) & SCC_RXRDY) == 0)
     49			;
     50		return in_8(sccd);
     51	}
     52	return -1;
     53}
     54
     55static unsigned char scc_inittab[] = {
     56    13, 0,		/* set baud rate divisor */
     57    12, 0,
     58    14, 1,		/* baud rate gen enable, src=rtxc */
     59    11, 0x50,		/* clocks = br gen */
     60    5,  0xea,		/* tx 8 bits, assert DTR & RTS */
     61    4,  0x46,		/* x16 clock, 1 stop */
     62    3,  0xc1,		/* rx enable, 8 bits */
     63};
     64
     65void __init udbg_scc_init(int force_scc)
     66{
     67	const u32 *reg;
     68	unsigned long addr;
     69	struct device_node *stdout = NULL, *escc = NULL, *macio = NULL;
     70	struct device_node *ch, *ch_def = NULL, *ch_a = NULL;
     71	const char *path;
     72	int i;
     73
     74	escc = of_find_node_by_name(NULL, "escc");
     75	if (escc == NULL)
     76		goto bail;
     77	macio = of_get_parent(escc);
     78	if (macio == NULL)
     79		goto bail;
     80	path = of_get_property(of_chosen, "linux,stdout-path", NULL);
     81	if (path != NULL)
     82		stdout = of_find_node_by_path(path);
     83	for_each_child_of_node(escc, ch) {
     84		if (ch == stdout)
     85			ch_def = of_node_get(ch);
     86		if (of_node_name_eq(ch, "ch-a"))
     87			ch_a = of_node_get(ch);
     88	}
     89	if (ch_def == NULL && !force_scc)
     90		goto bail;
     91
     92	ch = ch_def ? ch_def : ch_a;
     93
     94	/* Get address within mac-io ASIC */
     95	reg = of_get_property(escc, "reg", NULL);
     96	if (reg == NULL)
     97		goto bail;
     98	addr = reg[0];
     99
    100	/* Get address of mac-io PCI itself */
    101	reg = of_get_property(macio, "assigned-addresses", NULL);
    102	if (reg == NULL)
    103		goto bail;
    104	addr += reg[2];
    105
    106	/* Lock the serial port */
    107	pmac_call_feature(PMAC_FTR_SCC_ENABLE, ch,
    108			  PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
    109
    110	if (ch == ch_a)
    111		addr += 0x20;
    112	sccc = ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
    113	sccc += addr & ~PAGE_MASK;
    114	sccd = sccc + 0x10;
    115
    116	mb();
    117
    118	for (i = 20000; i != 0; --i)
    119		in_8(sccc);
    120	out_8(sccc, 0x09);		/* reset A or B side */
    121	out_8(sccc, 0xc0);
    122
    123	/* If SCC was the OF output port, read the BRG value, else
    124	 * Setup for 38400 or 57600 8N1 depending on the machine
    125	 */
    126	if (ch_def != NULL) {
    127		out_8(sccc, 13);
    128		scc_inittab[1] = in_8(sccc);
    129		out_8(sccc, 12);
    130		scc_inittab[3] = in_8(sccc);
    131	} else if (of_machine_is_compatible("RackMac1,1")
    132		   || of_machine_is_compatible("RackMac1,2")
    133		   || of_machine_is_compatible("MacRISC4")) {
    134		/* Xserves and G5s default to 57600 */
    135		scc_inittab[1] = 0;
    136		scc_inittab[3] = 0;
    137	} else {
    138		/* Others default to 38400 */
    139		scc_inittab[1] = 0;
    140		scc_inittab[3] = 1;
    141	}
    142
    143	for (i = 0; i < sizeof(scc_inittab); ++i)
    144		out_8(sccc, scc_inittab[i]);
    145
    146
    147	udbg_putc = udbg_scc_putc;
    148	udbg_getc = udbg_scc_getc;
    149	udbg_getc_poll = udbg_scc_getc_poll;
    150
    151	udbg_puts("Hello World !\n");
    152
    153 bail:
    154	of_node_put(macio);
    155	of_node_put(escc);
    156	of_node_put(stdout);
    157	of_node_put(ch_def);
    158	of_node_put(ch_a);
    159}
    160
    161#ifdef CONFIG_PPC64
    162static void udbg_real_scc_putc(char c)
    163{
    164	while ((real_readb(sccc) & SCC_TXRDY) == 0)
    165		;
    166	real_writeb(c, sccd);
    167	if (c == '\n')
    168		udbg_real_scc_putc('\r');
    169}
    170
    171void __init udbg_init_pmac_realmode(void)
    172{
    173	sccc = (volatile u8 __iomem *)0x80013020ul;
    174	sccd = (volatile u8 __iomem *)0x80013030ul;
    175
    176	udbg_putc = udbg_real_scc_putc;
    177	udbg_getc = NULL;
    178	udbg_getc_poll = NULL;
    179}
    180#endif /* CONFIG_PPC64 */