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

a20r.c (5302B)


      1/*
      2 * A20R specific code
      3 *
      4 * This file is subject to the terms and conditions of the GNU General Public
      5 * License.  See the file "COPYING" in the main directory of this archive
      6 * for more details.
      7 *
      8 * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
      9 */
     10
     11#include <linux/init.h>
     12#include <linux/interrupt.h>
     13#include <linux/irq.h>
     14#include <linux/platform_device.h>
     15#include <linux/serial_8250.h>
     16
     17#include <asm/sni.h>
     18#include <asm/time.h>
     19
     20#define PORT(_base,_irq)				\
     21	{						\
     22		.iobase		= _base,		\
     23		.irq		= _irq,			\
     24		.uartclk	= 1843200,		\
     25		.iotype		= UPIO_PORT,		\
     26		.flags		= UPF_BOOT_AUTOCONF,	\
     27	}
     28
     29static struct plat_serial8250_port a20r_data[] = {
     30	PORT(0x3f8, 4),
     31	PORT(0x2f8, 3),
     32	{ },
     33};
     34
     35static struct platform_device a20r_serial8250_device = {
     36	.name			= "serial8250",
     37	.id			= PLAT8250_DEV_PLATFORM,
     38	.dev			= {
     39		.platform_data	= a20r_data,
     40	},
     41};
     42
     43static struct resource a20r_ds1216_rsrc[] = {
     44	{
     45		.start = 0x1c081ffc,
     46		.end   = 0x1c081fff,
     47		.flags = IORESOURCE_MEM
     48	}
     49};
     50
     51static struct platform_device a20r_ds1216_device = {
     52	.name		= "rtc-ds1216",
     53	.num_resources	= ARRAY_SIZE(a20r_ds1216_rsrc),
     54	.resource	= a20r_ds1216_rsrc
     55};
     56
     57static struct resource snirm_82596_rsrc[] = {
     58	{
     59		.start = 0x18000000,
     60		.end   = 0x18000004,
     61		.flags = IORESOURCE_MEM
     62	},
     63	{
     64		.start = 0x18010000,
     65		.end   = 0x18010004,
     66		.flags = IORESOURCE_MEM
     67	},
     68	{
     69		.start = 0x1ff00000,
     70		.end   = 0x1ff00020,
     71		.flags = IORESOURCE_MEM
     72	},
     73	{
     74		.start = 22,
     75		.end   = 22,
     76		.flags = IORESOURCE_IRQ
     77	},
     78	{
     79		.flags = 0x01		     /* 16bit mpu port access */
     80	}
     81};
     82
     83static struct platform_device snirm_82596_pdev = {
     84	.name		= "snirm_82596",
     85	.num_resources	= ARRAY_SIZE(snirm_82596_rsrc),
     86	.resource	= snirm_82596_rsrc
     87};
     88
     89static struct resource snirm_53c710_rsrc[] = {
     90	{
     91		.start = 0x19000000,
     92		.end   = 0x190fffff,
     93		.flags = IORESOURCE_MEM
     94	},
     95	{
     96		.start = 19,
     97		.end   = 19,
     98		.flags = IORESOURCE_IRQ
     99	}
    100};
    101
    102static struct platform_device snirm_53c710_pdev = {
    103	.name		= "snirm_53c710",
    104	.num_resources	= ARRAY_SIZE(snirm_53c710_rsrc),
    105	.resource	= snirm_53c710_rsrc
    106};
    107
    108static struct resource sc26xx_rsrc[] = {
    109	{
    110		.start = 0x1c070000,
    111		.end   = 0x1c0700ff,
    112		.flags = IORESOURCE_MEM
    113	},
    114	{
    115		.start = 20,
    116		.end   = 20,
    117		.flags = IORESOURCE_IRQ
    118	}
    119};
    120
    121#include <linux/platform_data/serial-sccnxp.h>
    122
    123static struct sccnxp_pdata sccnxp_data = {
    124	.reg_shift	= 2,
    125	.mctrl_cfg[0]	= MCTRL_SIG(DTR_OP, LINE_OP7) |
    126			  MCTRL_SIG(RTS_OP, LINE_OP3) |
    127			  MCTRL_SIG(DSR_IP, LINE_IP5) |
    128			  MCTRL_SIG(DCD_IP, LINE_IP6),
    129	.mctrl_cfg[1]	= MCTRL_SIG(DTR_OP, LINE_OP2) |
    130			  MCTRL_SIG(RTS_OP, LINE_OP1) |
    131			  MCTRL_SIG(DSR_IP, LINE_IP0) |
    132			  MCTRL_SIG(CTS_IP, LINE_IP1) |
    133			  MCTRL_SIG(DCD_IP, LINE_IP2) |
    134			  MCTRL_SIG(RNG_IP, LINE_IP3),
    135};
    136
    137static struct platform_device sc26xx_pdev = {
    138	.name		= "sc2681",
    139	.resource	= sc26xx_rsrc,
    140	.num_resources	= ARRAY_SIZE(sc26xx_rsrc),
    141	.dev	= {
    142		.platform_data	= &sccnxp_data,
    143	},
    144};
    145
    146/*
    147 * Trigger chipset to update CPU's CAUSE IP field
    148 */
    149static u32 a20r_update_cause_ip(void)
    150{
    151	u32 status = read_c0_status();
    152
    153	write_c0_status(status | 0x00010000);
    154	asm volatile(
    155	"	.set	push			\n"
    156	"	.set	noat			\n"
    157	"	.set	noreorder		\n"
    158	"	lw	$1, 0(%0)		\n"
    159	"	sb	$0, 0(%1)		\n"
    160	"	sync				\n"
    161	"	lb	%1, 0(%1)		\n"
    162	"	b	1f			\n"
    163	"	ori	%1, $1, 2		\n"
    164	"	.align	8			\n"
    165	"1:					\n"
    166	"	nop				\n"
    167	"	sw	%1, 0(%0)		\n"
    168	"	sync				\n"
    169	"	li	%1, 0x20		\n"
    170	"2:					\n"
    171	"	nop				\n"
    172	"	bnez	%1,2b			\n"
    173	"	addiu	%1, -1			\n"
    174	"	sw	$1, 0(%0)		\n"
    175	"	sync				\n"
    176		".set	pop			\n"
    177	:
    178	: "Jr" (PCIMT_UCONF), "Jr" (0xbc000000));
    179	write_c0_status(status);
    180
    181	return status;
    182}
    183
    184static inline void unmask_a20r_irq(struct irq_data *d)
    185{
    186	set_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE));
    187	irq_enable_hazard();
    188}
    189
    190static inline void mask_a20r_irq(struct irq_data *d)
    191{
    192	clear_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE));
    193	irq_disable_hazard();
    194}
    195
    196static struct irq_chip a20r_irq_type = {
    197	.name		= "A20R",
    198	.irq_mask	= mask_a20r_irq,
    199	.irq_unmask	= unmask_a20r_irq,
    200};
    201
    202/*
    203 * hwint 0 receive all interrupts
    204 */
    205static void a20r_hwint(void)
    206{
    207	u32 cause, status;
    208	int irq;
    209
    210	clear_c0_status(IE_IRQ0);
    211	status = a20r_update_cause_ip();
    212	cause = read_c0_cause();
    213
    214	irq = ffs(((cause & status) >> 8) & 0xf8);
    215	if (likely(irq > 0))
    216		do_IRQ(SNI_A20R_IRQ_BASE + irq - 1);
    217
    218	a20r_update_cause_ip();
    219	set_c0_status(IE_IRQ0);
    220}
    221
    222void __init sni_a20r_irq_init(void)
    223{
    224	int i;
    225
    226	for (i = SNI_A20R_IRQ_BASE + 2 ; i < SNI_A20R_IRQ_BASE + 8; i++)
    227		irq_set_chip_and_handler(i, &a20r_irq_type, handle_level_irq);
    228	sni_hwint = a20r_hwint;
    229	change_c0_status(ST0_IM, IE_IRQ0);
    230	if (request_irq(SNI_A20R_IRQ_BASE + 3, sni_isa_irq_handler,
    231			IRQF_SHARED, "ISA", sni_isa_irq_handler))
    232		pr_err("Failed to register ISA interrupt\n");
    233}
    234
    235void sni_a20r_init(void)
    236{
    237	/* FIXME, remove if not needed */
    238}
    239
    240static int __init snirm_a20r_setup_devinit(void)
    241{
    242	switch (sni_brd_type) {
    243	case SNI_BRD_TOWER_OASIC:
    244	case SNI_BRD_MINITOWER:
    245		platform_device_register(&snirm_82596_pdev);
    246		platform_device_register(&snirm_53c710_pdev);
    247		platform_device_register(&sc26xx_pdev);
    248		platform_device_register(&a20r_serial8250_device);
    249		platform_device_register(&a20r_ds1216_device);
    250		sni_eisa_root_init();
    251		break;
    252	}
    253	return 0;
    254}
    255
    256device_initcall(snirm_a20r_setup_devinit);