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

central.c (6127B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* central.c: Central FHC driver for Sunfire/Starfire/Wildfire.
      3 *
      4 * Copyright (C) 1997, 1999, 2008 David S. Miller (davem@davemloft.net)
      5 */
      6
      7#include <linux/kernel.h>
      8#include <linux/types.h>
      9#include <linux/slab.h>
     10#include <linux/export.h>
     11#include <linux/string.h>
     12#include <linux/init.h>
     13#include <linux/of_device.h>
     14#include <linux/platform_device.h>
     15
     16#include <asm/fhc.h>
     17#include <asm/upa.h>
     18
     19struct clock_board {
     20	void __iomem		*clock_freq_regs;
     21	void __iomem		*clock_regs;
     22	void __iomem		*clock_ver_reg;
     23	int			num_slots;
     24	struct resource		leds_resource;
     25	struct platform_device	leds_pdev;
     26};
     27
     28struct fhc {
     29	void __iomem		*pregs;
     30	bool			central;
     31	bool			jtag_master;
     32	int			board_num;
     33	struct resource		leds_resource;
     34	struct platform_device	leds_pdev;
     35};
     36
     37static int clock_board_calc_nslots(struct clock_board *p)
     38{
     39	u8 reg = upa_readb(p->clock_regs + CLOCK_STAT1) & 0xc0;
     40
     41	switch (reg) {
     42	case 0x40:
     43		return 16;
     44
     45	case 0xc0:
     46		return 8;
     47
     48	case 0x80:
     49		reg = 0;
     50		if (p->clock_ver_reg)
     51			reg = upa_readb(p->clock_ver_reg);
     52		if (reg) {
     53			if (reg & 0x80)
     54				return 4;
     55			else
     56				return 5;
     57		}
     58		fallthrough;
     59	default:
     60		return 4;
     61	}
     62}
     63
     64static int clock_board_probe(struct platform_device *op)
     65{
     66	struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL);
     67	int err = -ENOMEM;
     68
     69	if (!p) {
     70		printk(KERN_ERR "clock_board: Cannot allocate struct clock_board\n");
     71		goto out;
     72	}
     73
     74	p->clock_freq_regs = of_ioremap(&op->resource[0], 0,
     75					resource_size(&op->resource[0]),
     76					"clock_board_freq");
     77	if (!p->clock_freq_regs) {
     78		printk(KERN_ERR "clock_board: Cannot map clock_freq_regs\n");
     79		goto out_free;
     80	}
     81
     82	p->clock_regs = of_ioremap(&op->resource[1], 0,
     83				   resource_size(&op->resource[1]),
     84				   "clock_board_regs");
     85	if (!p->clock_regs) {
     86		printk(KERN_ERR "clock_board: Cannot map clock_regs\n");
     87		goto out_unmap_clock_freq_regs;
     88	}
     89
     90	if (op->resource[2].flags) {
     91		p->clock_ver_reg = of_ioremap(&op->resource[2], 0,
     92					      resource_size(&op->resource[2]),
     93					      "clock_ver_reg");
     94		if (!p->clock_ver_reg) {
     95			printk(KERN_ERR "clock_board: Cannot map clock_ver_reg\n");
     96			goto out_unmap_clock_regs;
     97		}
     98	}
     99
    100	p->num_slots = clock_board_calc_nslots(p);
    101
    102	p->leds_resource.start = (unsigned long)
    103		(p->clock_regs + CLOCK_CTRL);
    104	p->leds_resource.end = p->leds_resource.start;
    105	p->leds_resource.name = "leds";
    106
    107	p->leds_pdev.name = "sunfire-clockboard-leds";
    108	p->leds_pdev.id = -1;
    109	p->leds_pdev.resource = &p->leds_resource;
    110	p->leds_pdev.num_resources = 1;
    111	p->leds_pdev.dev.parent = &op->dev;
    112
    113	err = platform_device_register(&p->leds_pdev);
    114	if (err) {
    115		printk(KERN_ERR "clock_board: Could not register LEDS "
    116		       "platform device\n");
    117		goto out_unmap_clock_ver_reg;
    118	}
    119
    120	printk(KERN_INFO "clock_board: Detected %d slot Enterprise system.\n",
    121	       p->num_slots);
    122
    123	err = 0;
    124out:
    125	return err;
    126
    127out_unmap_clock_ver_reg:
    128	if (p->clock_ver_reg)
    129		of_iounmap(&op->resource[2], p->clock_ver_reg,
    130			   resource_size(&op->resource[2]));
    131
    132out_unmap_clock_regs:
    133	of_iounmap(&op->resource[1], p->clock_regs,
    134		   resource_size(&op->resource[1]));
    135
    136out_unmap_clock_freq_regs:
    137	of_iounmap(&op->resource[0], p->clock_freq_regs,
    138		   resource_size(&op->resource[0]));
    139
    140out_free:
    141	kfree(p);
    142	goto out;
    143}
    144
    145static const struct of_device_id clock_board_match[] = {
    146	{
    147		.name = "clock-board",
    148	},
    149	{},
    150};
    151
    152static struct platform_driver clock_board_driver = {
    153	.probe		= clock_board_probe,
    154	.driver = {
    155		.name = "clock_board",
    156		.of_match_table = clock_board_match,
    157	},
    158};
    159
    160static int fhc_probe(struct platform_device *op)
    161{
    162	struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL);
    163	int err = -ENOMEM;
    164	u32 reg;
    165
    166	if (!p) {
    167		printk(KERN_ERR "fhc: Cannot allocate struct fhc\n");
    168		goto out;
    169	}
    170
    171	if (of_node_name_eq(op->dev.of_node->parent, "central"))
    172		p->central = true;
    173
    174	p->pregs = of_ioremap(&op->resource[0], 0,
    175			      resource_size(&op->resource[0]),
    176			      "fhc_pregs");
    177	if (!p->pregs) {
    178		printk(KERN_ERR "fhc: Cannot map pregs\n");
    179		goto out_free;
    180	}
    181
    182	if (p->central) {
    183		reg = upa_readl(p->pregs + FHC_PREGS_BSR);
    184		p->board_num = ((reg >> 16) & 1) | ((reg >> 12) & 0x0e);
    185	} else {
    186		p->board_num = of_getintprop_default(op->dev.of_node, "board#", -1);
    187		if (p->board_num == -1) {
    188			printk(KERN_ERR "fhc: No board# property\n");
    189			goto out_unmap_pregs;
    190		}
    191		if (upa_readl(p->pregs + FHC_PREGS_JCTRL) & FHC_JTAG_CTRL_MENAB)
    192			p->jtag_master = true;
    193	}
    194
    195	if (!p->central) {
    196		p->leds_resource.start = (unsigned long)
    197			(p->pregs + FHC_PREGS_CTRL);
    198		p->leds_resource.end = p->leds_resource.start;
    199		p->leds_resource.name = "leds";
    200
    201		p->leds_pdev.name = "sunfire-fhc-leds";
    202		p->leds_pdev.id = p->board_num;
    203		p->leds_pdev.resource = &p->leds_resource;
    204		p->leds_pdev.num_resources = 1;
    205		p->leds_pdev.dev.parent = &op->dev;
    206
    207		err = platform_device_register(&p->leds_pdev);
    208		if (err) {
    209			printk(KERN_ERR "fhc: Could not register LEDS "
    210			       "platform device\n");
    211			goto out_unmap_pregs;
    212		}
    213	}
    214	reg = upa_readl(p->pregs + FHC_PREGS_CTRL);
    215
    216	if (!p->central)
    217		reg |= FHC_CONTROL_IXIST;
    218
    219	reg &= ~(FHC_CONTROL_AOFF |
    220		 FHC_CONTROL_BOFF |
    221		 FHC_CONTROL_SLINE);
    222
    223	upa_writel(reg, p->pregs + FHC_PREGS_CTRL);
    224	upa_readl(p->pregs + FHC_PREGS_CTRL);
    225
    226	reg = upa_readl(p->pregs + FHC_PREGS_ID);
    227	printk(KERN_INFO "fhc: Board #%d, Version[%x] PartID[%x] Manuf[%x] %s\n",
    228	       p->board_num,
    229	       (reg & FHC_ID_VERS) >> 28,
    230	       (reg & FHC_ID_PARTID) >> 12,
    231	       (reg & FHC_ID_MANUF) >> 1,
    232	       (p->jtag_master ?
    233		"(JTAG Master)" :
    234		(p->central ? "(Central)" : "")));
    235
    236	err = 0;
    237
    238out:
    239	return err;
    240
    241out_unmap_pregs:
    242	of_iounmap(&op->resource[0], p->pregs, resource_size(&op->resource[0]));
    243
    244out_free:
    245	kfree(p);
    246	goto out;
    247}
    248
    249static const struct of_device_id fhc_match[] = {
    250	{
    251		.name = "fhc",
    252	},
    253	{},
    254};
    255
    256static struct platform_driver fhc_driver = {
    257	.probe		= fhc_probe,
    258	.driver = {
    259		.name = "fhc",
    260		.of_match_table = fhc_match,
    261	},
    262};
    263
    264static int __init sunfire_init(void)
    265{
    266	(void) platform_driver_register(&fhc_driver);
    267	(void) platform_driver_register(&clock_board_driver);
    268	return 0;
    269}
    270
    271fs_initcall(sunfire_init);