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

driver_mipscore.c (8982B)


      1/*
      2 * Sonics Silicon Backplane
      3 * Broadcom MIPS core driver
      4 *
      5 * Copyright 2005, Broadcom Corporation
      6 * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
      7 *
      8 * Licensed under the GNU/GPL. See COPYING for details.
      9 */
     10
     11#include "ssb_private.h"
     12
     13#include <linux/ssb/ssb.h>
     14
     15#include <linux/mtd/physmap.h>
     16#include <linux/serial.h>
     17#include <linux/serial_core.h>
     18#include <linux/serial_reg.h>
     19#include <linux/time.h>
     20#ifdef CONFIG_BCM47XX
     21#include <linux/bcm47xx_nvram.h>
     22#endif
     23
     24static const char * const part_probes[] = { "bcm47xxpart", NULL };
     25
     26static struct physmap_flash_data ssb_pflash_data = {
     27	.part_probe_types	= part_probes,
     28};
     29
     30static struct resource ssb_pflash_resource = {
     31	.name	= "ssb_pflash",
     32	.flags  = IORESOURCE_MEM,
     33};
     34
     35struct platform_device ssb_pflash_dev = {
     36	.name		= "physmap-flash",
     37	.dev		= {
     38		.platform_data  = &ssb_pflash_data,
     39	},
     40	.resource	= &ssb_pflash_resource,
     41	.num_resources	= 1,
     42};
     43
     44static inline u32 mips_read32(struct ssb_mipscore *mcore,
     45			      u16 offset)
     46{
     47	return ssb_read32(mcore->dev, offset);
     48}
     49
     50static inline void mips_write32(struct ssb_mipscore *mcore,
     51				u16 offset,
     52				u32 value)
     53{
     54	ssb_write32(mcore->dev, offset, value);
     55}
     56
     57static const u32 ipsflag_irq_mask[] = {
     58	0,
     59	SSB_IPSFLAG_IRQ1,
     60	SSB_IPSFLAG_IRQ2,
     61	SSB_IPSFLAG_IRQ3,
     62	SSB_IPSFLAG_IRQ4,
     63};
     64
     65static const u32 ipsflag_irq_shift[] = {
     66	0,
     67	SSB_IPSFLAG_IRQ1_SHIFT,
     68	SSB_IPSFLAG_IRQ2_SHIFT,
     69	SSB_IPSFLAG_IRQ3_SHIFT,
     70	SSB_IPSFLAG_IRQ4_SHIFT,
     71};
     72
     73static inline u32 ssb_irqflag(struct ssb_device *dev)
     74{
     75	u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
     76	if (tpsflag)
     77		return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
     78	else
     79		/* not irq supported */
     80		return 0x3f;
     81}
     82
     83static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag)
     84{
     85	struct ssb_bus *bus = rdev->bus;
     86	int i;
     87	for (i = 0; i < bus->nr_devices; i++) {
     88		struct ssb_device *dev;
     89		dev = &(bus->devices[i]);
     90		if (ssb_irqflag(dev) == irqflag)
     91			return dev;
     92	}
     93	return NULL;
     94}
     95
     96/* Get the MIPS IRQ assignment for a specified device.
     97 * If unassigned, 0 is returned.
     98 * If disabled, 5 is returned.
     99 * If not supported, 6 is returned.
    100 */
    101unsigned int ssb_mips_irq(struct ssb_device *dev)
    102{
    103	struct ssb_bus *bus = dev->bus;
    104	struct ssb_device *mdev = bus->mipscore.dev;
    105	u32 irqflag;
    106	u32 ipsflag;
    107	u32 tmp;
    108	unsigned int irq;
    109
    110	irqflag = ssb_irqflag(dev);
    111	if (irqflag == 0x3f)
    112		return 6;
    113	ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG);
    114	for (irq = 1; irq <= 4; irq++) {
    115		tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]);
    116		if (tmp == irqflag)
    117			break;
    118	}
    119	if (irq	== 5) {
    120		if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))
    121			irq = 0;
    122	}
    123
    124	return irq;
    125}
    126
    127static void clear_irq(struct ssb_bus *bus, unsigned int irq)
    128{
    129	struct ssb_device *dev = bus->mipscore.dev;
    130
    131	/* Clear the IRQ in the MIPScore backplane registers */
    132	if (irq == 0) {
    133		ssb_write32(dev, SSB_INTVEC, 0);
    134	} else {
    135		ssb_write32(dev, SSB_IPSFLAG,
    136			    ssb_read32(dev, SSB_IPSFLAG) |
    137			    ipsflag_irq_mask[irq]);
    138	}
    139}
    140
    141static void set_irq(struct ssb_device *dev, unsigned int irq)
    142{
    143	unsigned int oldirq = ssb_mips_irq(dev);
    144	struct ssb_bus *bus = dev->bus;
    145	struct ssb_device *mdev = bus->mipscore.dev;
    146	u32 irqflag = ssb_irqflag(dev);
    147
    148	BUG_ON(oldirq == 6);
    149
    150	dev->irq = irq + 2;
    151
    152	/* clear the old irq */
    153	if (oldirq == 0)
    154		ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)));
    155	else if (oldirq != 5)
    156		clear_irq(bus, oldirq);
    157
    158	/* assign the new one */
    159	if (irq == 0) {
    160		ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC)));
    161	} else {
    162		u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG);
    163		if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) {
    164			u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq];
    165			struct ssb_device *olddev = find_device(dev, oldipsflag);
    166			if (olddev)
    167				set_irq(olddev, 0);
    168		}
    169		irqflag <<= ipsflag_irq_shift[irq];
    170		irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]);
    171		ssb_write32(mdev, SSB_IPSFLAG, irqflag);
    172	}
    173	dev_dbg(dev->dev, "set_irq: core 0x%04x, irq %d => %d\n",
    174		dev->id.coreid, oldirq+2, irq+2);
    175}
    176
    177static void print_irq(struct ssb_device *dev, unsigned int irq)
    178{
    179	static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
    180	dev_dbg(dev->dev,
    181		"core 0x%04x, irq : %s%s %s%s %s%s %s%s %s%s %s%s %s%s\n",
    182		dev->id.coreid,
    183		irq_name[0], irq == 0 ? "*" : " ",
    184		irq_name[1], irq == 1 ? "*" : " ",
    185		irq_name[2], irq == 2 ? "*" : " ",
    186		irq_name[3], irq == 3 ? "*" : " ",
    187		irq_name[4], irq == 4 ? "*" : " ",
    188		irq_name[5], irq == 5 ? "*" : " ",
    189		irq_name[6], irq == 6 ? "*" : " ");
    190}
    191
    192static void dump_irq(struct ssb_bus *bus)
    193{
    194	int i;
    195	for (i = 0; i < bus->nr_devices; i++) {
    196		struct ssb_device *dev;
    197		dev = &(bus->devices[i]);
    198		print_irq(dev, ssb_mips_irq(dev));
    199	}
    200}
    201
    202static void ssb_mips_serial_init(struct ssb_mipscore *mcore)
    203{
    204	struct ssb_bus *bus = mcore->dev->bus;
    205
    206	if (ssb_extif_available(&bus->extif))
    207		mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports);
    208	else if (ssb_chipco_available(&bus->chipco))
    209		mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports);
    210	else
    211		mcore->nr_serial_ports = 0;
    212}
    213
    214static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)
    215{
    216	struct ssb_bus *bus = mcore->dev->bus;
    217	struct ssb_sflash *sflash = &mcore->sflash;
    218	struct ssb_pflash *pflash = &mcore->pflash;
    219
    220	/* When there is no chipcommon on the bus there is 4MB flash */
    221	if (!ssb_chipco_available(&bus->chipco)) {
    222		pflash->present = true;
    223		pflash->buswidth = 2;
    224		pflash->window = SSB_FLASH1;
    225		pflash->window_size = SSB_FLASH1_SZ;
    226		goto ssb_pflash;
    227	}
    228
    229	/* There is ChipCommon, so use it to read info about flash */
    230	switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) {
    231	case SSB_CHIPCO_FLASHT_STSER:
    232	case SSB_CHIPCO_FLASHT_ATSER:
    233		dev_dbg(mcore->dev->dev, "Found serial flash\n");
    234		ssb_sflash_init(&bus->chipco);
    235		break;
    236	case SSB_CHIPCO_FLASHT_PARA:
    237		dev_dbg(mcore->dev->dev, "Found parallel flash\n");
    238		pflash->present = true;
    239		pflash->window = SSB_FLASH2;
    240		pflash->window_size = SSB_FLASH2_SZ;
    241		if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG)
    242		               & SSB_CHIPCO_CFG_DS16) == 0)
    243			pflash->buswidth = 1;
    244		else
    245			pflash->buswidth = 2;
    246		break;
    247	}
    248
    249ssb_pflash:
    250	if (sflash->present) {
    251#ifdef CONFIG_BCM47XX
    252		bcm47xx_nvram_init_from_mem(sflash->window, sflash->size);
    253#endif
    254	} else if (pflash->present) {
    255#ifdef CONFIG_BCM47XX
    256		bcm47xx_nvram_init_from_mem(pflash->window, pflash->window_size);
    257#endif
    258
    259		ssb_pflash_data.width = pflash->buswidth;
    260		ssb_pflash_resource.start = pflash->window;
    261		ssb_pflash_resource.end = pflash->window + pflash->window_size;
    262	}
    263}
    264
    265u32 ssb_cpu_clock(struct ssb_mipscore *mcore)
    266{
    267	struct ssb_bus *bus = mcore->dev->bus;
    268	u32 pll_type, n, m, rate = 0;
    269
    270	if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
    271		return ssb_pmu_get_cpu_clock(&bus->chipco);
    272
    273	if (ssb_extif_available(&bus->extif)) {
    274		ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
    275	} else if (ssb_chipco_available(&bus->chipco)) {
    276		ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m);
    277	} else
    278		return 0;
    279
    280	if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) {
    281		rate = 200000000;
    282	} else {
    283		rate = ssb_calc_clock_rate(pll_type, n, m);
    284	}
    285
    286	if (pll_type == SSB_PLLTYPE_6) {
    287		rate *= 2;
    288	}
    289
    290	return rate;
    291}
    292
    293void ssb_mipscore_init(struct ssb_mipscore *mcore)
    294{
    295	struct ssb_bus *bus;
    296	struct ssb_device *dev;
    297	unsigned long hz, ns;
    298	unsigned int irq, i;
    299
    300	if (!mcore->dev)
    301		return; /* We don't have a MIPS core */
    302
    303	dev_dbg(mcore->dev->dev, "Initializing MIPS core...\n");
    304
    305	bus = mcore->dev->bus;
    306	hz = ssb_clockspeed(bus);
    307	if (!hz)
    308		hz = 100000000;
    309	ns = 1000000000 / hz;
    310
    311	if (ssb_extif_available(&bus->extif))
    312		ssb_extif_timing_init(&bus->extif, ns);
    313	else if (ssb_chipco_available(&bus->chipco))
    314		ssb_chipco_timing_init(&bus->chipco, ns);
    315
    316	/* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
    317	for (irq = 2, i = 0; i < bus->nr_devices; i++) {
    318		int mips_irq;
    319		dev = &(bus->devices[i]);
    320		mips_irq = ssb_mips_irq(dev);
    321		if (mips_irq > 4)
    322			dev->irq = 0;
    323		else
    324			dev->irq = mips_irq + 2;
    325		if (dev->irq > 5)
    326			continue;
    327		switch (dev->id.coreid) {
    328		case SSB_DEV_USB11_HOST:
    329			/* shouldn't need a separate irq line for non-4710, most of them have a proper
    330			 * external usb controller on the pci */
    331			if ((bus->chip_id == 0x4710) && (irq <= 4)) {
    332				set_irq(dev, irq++);
    333			}
    334			break;
    335		case SSB_DEV_PCI:
    336		case SSB_DEV_ETHERNET:
    337		case SSB_DEV_ETHERNET_GBIT:
    338		case SSB_DEV_80211:
    339		case SSB_DEV_USB20_HOST:
    340			/* These devices get their own IRQ line if available, the rest goes on IRQ0 */
    341			if (irq <= 4) {
    342				set_irq(dev, irq++);
    343				break;
    344			}
    345			fallthrough;
    346		case SSB_DEV_EXTIF:
    347			set_irq(dev, 0);
    348			break;
    349		}
    350	}
    351	dev_dbg(mcore->dev->dev, "after irq reconfiguration\n");
    352	dump_irq(bus);
    353
    354	ssb_mips_serial_init(mcore);
    355	ssb_mips_flash_detect(mcore);
    356}