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

intel_init.c (10212B)


      1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
      2// Copyright(c) 2015-17 Intel Corporation.
      3
      4/*
      5 * SDW Intel Init Routines
      6 *
      7 * Initializes and creates SDW devices based on ACPI and Hardware values
      8 */
      9
     10#include <linux/acpi.h>
     11#include <linux/export.h>
     12#include <linux/interrupt.h>
     13#include <linux/io.h>
     14#include <linux/module.h>
     15#include <linux/auxiliary_bus.h>
     16#include <linux/pm_runtime.h>
     17#include <linux/soundwire/sdw_intel.h>
     18#include "cadence_master.h"
     19#include "intel.h"
     20
     21static void intel_link_dev_release(struct device *dev)
     22{
     23	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
     24	struct sdw_intel_link_dev *ldev = auxiliary_dev_to_sdw_intel_link_dev(auxdev);
     25
     26	kfree(ldev);
     27}
     28
     29/* alloc, init and add link devices */
     30static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res *res,
     31							  struct sdw_intel_ctx *ctx,
     32							  struct fwnode_handle *fwnode,
     33							  const char *name,
     34							  int link_id)
     35{
     36	struct sdw_intel_link_dev *ldev;
     37	struct sdw_intel_link_res *link;
     38	struct auxiliary_device *auxdev;
     39	int ret;
     40
     41	ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
     42	if (!ldev)
     43		return ERR_PTR(-ENOMEM);
     44
     45	auxdev = &ldev->auxdev;
     46	auxdev->name = name;
     47	auxdev->dev.parent = res->parent;
     48	auxdev->dev.fwnode = fwnode;
     49	auxdev->dev.release = intel_link_dev_release;
     50
     51	/* we don't use an IDA since we already have a link ID */
     52	auxdev->id = link_id;
     53
     54	/*
     55	 * keep a handle on the allocated memory, to be used in all other functions.
     56	 * Since the same pattern is used to skip links that are not enabled, there is
     57	 * no need to check if ctx->ldev[i] is NULL later on.
     58	 */
     59	ctx->ldev[link_id] = ldev;
     60
     61	/* Add link information used in the driver probe */
     62	link = &ldev->link_res;
     63	link->mmio_base = res->mmio_base;
     64	link->registers = res->mmio_base + SDW_LINK_BASE
     65		+ (SDW_LINK_SIZE * link_id);
     66	link->shim = res->mmio_base + res->shim_base;
     67	link->alh = res->mmio_base + res->alh_base;
     68
     69	link->ops = res->ops;
     70	link->dev = res->dev;
     71
     72	link->clock_stop_quirks = res->clock_stop_quirks;
     73	link->shim_lock = &ctx->shim_lock;
     74	link->shim_mask = &ctx->shim_mask;
     75	link->link_mask = ctx->link_mask;
     76
     77	/* now follow the two-step init/add sequence */
     78	ret = auxiliary_device_init(auxdev);
     79	if (ret < 0) {
     80		dev_err(res->parent, "failed to initialize link dev %s link_id %d\n",
     81			name, link_id);
     82		kfree(ldev);
     83		return ERR_PTR(ret);
     84	}
     85
     86	ret = auxiliary_device_add(&ldev->auxdev);
     87	if (ret < 0) {
     88		dev_err(res->parent, "failed to add link dev %s link_id %d\n",
     89			ldev->auxdev.name, link_id);
     90		/* ldev will be freed with the put_device() and .release sequence */
     91		auxiliary_device_uninit(&ldev->auxdev);
     92		return ERR_PTR(ret);
     93	}
     94
     95	return ldev;
     96}
     97
     98static void intel_link_dev_unregister(struct sdw_intel_link_dev *ldev)
     99{
    100	auxiliary_device_delete(&ldev->auxdev);
    101	auxiliary_device_uninit(&ldev->auxdev);
    102}
    103
    104static int sdw_intel_cleanup(struct sdw_intel_ctx *ctx)
    105{
    106	struct sdw_intel_link_dev *ldev;
    107	u32 link_mask;
    108	int i;
    109
    110	link_mask = ctx->link_mask;
    111
    112	for (i = 0; i < ctx->count; i++) {
    113		if (!(link_mask & BIT(i)))
    114			continue;
    115
    116		ldev = ctx->ldev[i];
    117
    118		pm_runtime_disable(&ldev->auxdev.dev);
    119		if (!ldev->link_res.clock_stop_quirks)
    120			pm_runtime_put_noidle(ldev->link_res.dev);
    121
    122		intel_link_dev_unregister(ldev);
    123	}
    124
    125	return 0;
    126}
    127
    128#define HDA_DSP_REG_ADSPIC2             (0x10)
    129#define HDA_DSP_REG_ADSPIS2             (0x14)
    130#define HDA_DSP_REG_ADSPIC2_SNDW        BIT(5)
    131
    132/**
    133 * sdw_intel_enable_irq() - enable/disable Intel SoundWire IRQ
    134 * @mmio_base: The mmio base of the control register
    135 * @enable: true if enable
    136 */
    137void sdw_intel_enable_irq(void __iomem *mmio_base, bool enable)
    138{
    139	u32 val;
    140
    141	val = readl(mmio_base + HDA_DSP_REG_ADSPIC2);
    142
    143	if (enable)
    144		val |= HDA_DSP_REG_ADSPIC2_SNDW;
    145	else
    146		val &= ~HDA_DSP_REG_ADSPIC2_SNDW;
    147
    148	writel(val, mmio_base + HDA_DSP_REG_ADSPIC2);
    149}
    150EXPORT_SYMBOL_NS(sdw_intel_enable_irq, SOUNDWIRE_INTEL_INIT);
    151
    152irqreturn_t sdw_intel_thread(int irq, void *dev_id)
    153{
    154	struct sdw_intel_ctx *ctx = dev_id;
    155	struct sdw_intel_link_res *link;
    156
    157	list_for_each_entry(link, &ctx->link_list, list)
    158		sdw_cdns_irq(irq, link->cdns);
    159
    160	sdw_intel_enable_irq(ctx->mmio_base, true);
    161	return IRQ_HANDLED;
    162}
    163EXPORT_SYMBOL_NS(sdw_intel_thread, SOUNDWIRE_INTEL_INIT);
    164
    165static struct sdw_intel_ctx
    166*sdw_intel_probe_controller(struct sdw_intel_res *res)
    167{
    168	struct sdw_intel_link_res *link;
    169	struct sdw_intel_link_dev *ldev;
    170	struct sdw_intel_ctx *ctx;
    171	struct acpi_device *adev;
    172	struct sdw_slave *slave;
    173	struct list_head *node;
    174	struct sdw_bus *bus;
    175	u32 link_mask;
    176	int num_slaves = 0;
    177	int count;
    178	int i;
    179
    180	if (!res)
    181		return NULL;
    182
    183	adev = acpi_fetch_acpi_dev(res->handle);
    184	if (!adev)
    185		return NULL;
    186
    187	if (!res->count)
    188		return NULL;
    189
    190	count = res->count;
    191	dev_dbg(&adev->dev, "Creating %d SDW Link devices\n", count);
    192
    193	/*
    194	 * we need to alloc/free memory manually and can't use devm:
    195	 * this routine may be called from a workqueue, and not from
    196	 * the parent .probe.
    197	 * If devm_ was used, the memory might never be freed on errors.
    198	 */
    199	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
    200	if (!ctx)
    201		return NULL;
    202
    203	ctx->count = count;
    204
    205	/*
    206	 * allocate the array of pointers. The link-specific data is allocated
    207	 * as part of the first loop below and released with the auxiliary_device_uninit().
    208	 * If some links are disabled, the link pointer will remain NULL. Given that the
    209	 * number of links is small, this is simpler than using a list to keep track of links.
    210	 */
    211	ctx->ldev = kcalloc(ctx->count, sizeof(*ctx->ldev), GFP_KERNEL);
    212	if (!ctx->ldev) {
    213		kfree(ctx);
    214		return NULL;
    215	}
    216
    217	ctx->mmio_base = res->mmio_base;
    218	ctx->shim_base = res->shim_base;
    219	ctx->alh_base = res->alh_base;
    220	ctx->link_mask = res->link_mask;
    221	ctx->handle = res->handle;
    222	mutex_init(&ctx->shim_lock);
    223
    224	link_mask = ctx->link_mask;
    225
    226	INIT_LIST_HEAD(&ctx->link_list);
    227
    228	for (i = 0; i < count; i++) {
    229		if (!(link_mask & BIT(i)))
    230			continue;
    231
    232		/*
    233		 * init and add a device for each link
    234		 *
    235		 * The name of the device will be soundwire_intel.link.[i],
    236		 * with the "soundwire_intel" module prefix automatically added
    237		 * by the auxiliary bus core.
    238		 */
    239		ldev = intel_link_dev_register(res,
    240					       ctx,
    241					       acpi_fwnode_handle(adev),
    242					       "link",
    243					       i);
    244		if (IS_ERR(ldev))
    245			goto err;
    246
    247		link = &ldev->link_res;
    248		link->cdns = auxiliary_get_drvdata(&ldev->auxdev);
    249
    250		if (!link->cdns) {
    251			dev_err(&adev->dev, "failed to get link->cdns\n");
    252			/*
    253			 * 1 will be subtracted from i in the err label, but we need to call
    254			 * intel_link_dev_unregister for this ldev, so plus 1 now
    255			 */
    256			i++;
    257			goto err;
    258		}
    259		list_add_tail(&link->list, &ctx->link_list);
    260		bus = &link->cdns->bus;
    261		/* Calculate number of slaves */
    262		list_for_each(node, &bus->slaves)
    263			num_slaves++;
    264	}
    265
    266	ctx->ids = kcalloc(num_slaves, sizeof(*ctx->ids), GFP_KERNEL);
    267	if (!ctx->ids)
    268		goto err;
    269
    270	ctx->num_slaves = num_slaves;
    271	i = 0;
    272	list_for_each_entry(link, &ctx->link_list, list) {
    273		bus = &link->cdns->bus;
    274		list_for_each_entry(slave, &bus->slaves, node) {
    275			ctx->ids[i].id = slave->id;
    276			ctx->ids[i].link_id = bus->link_id;
    277			i++;
    278		}
    279	}
    280
    281	return ctx;
    282
    283err:
    284	while (i--) {
    285		if (!(link_mask & BIT(i)))
    286			continue;
    287		ldev = ctx->ldev[i];
    288		intel_link_dev_unregister(ldev);
    289	}
    290	kfree(ctx->ldev);
    291	kfree(ctx);
    292	return NULL;
    293}
    294
    295static int
    296sdw_intel_startup_controller(struct sdw_intel_ctx *ctx)
    297{
    298	struct acpi_device *adev = acpi_fetch_acpi_dev(ctx->handle);
    299	struct sdw_intel_link_dev *ldev;
    300	u32 caps;
    301	u32 link_mask;
    302	int i;
    303
    304	if (!adev)
    305		return -EINVAL;
    306
    307	/* Check SNDWLCAP.LCOUNT */
    308	caps = ioread32(ctx->mmio_base + ctx->shim_base + SDW_SHIM_LCAP);
    309	caps &= GENMASK(2, 0);
    310
    311	/* Check HW supported vs property value */
    312	if (caps < ctx->count) {
    313		dev_err(&adev->dev,
    314			"BIOS master count is larger than hardware capabilities\n");
    315		return -EINVAL;
    316	}
    317
    318	if (!ctx->ldev)
    319		return -EINVAL;
    320
    321	link_mask = ctx->link_mask;
    322
    323	/* Startup SDW Master devices */
    324	for (i = 0; i < ctx->count; i++) {
    325		if (!(link_mask & BIT(i)))
    326			continue;
    327
    328		ldev = ctx->ldev[i];
    329
    330		intel_link_startup(&ldev->auxdev);
    331
    332		if (!ldev->link_res.clock_stop_quirks) {
    333			/*
    334			 * we need to prevent the parent PCI device
    335			 * from entering pm_runtime suspend, so that
    336			 * power rails to the SoundWire IP are not
    337			 * turned off.
    338			 */
    339			pm_runtime_get_noresume(ldev->link_res.dev);
    340		}
    341	}
    342
    343	return 0;
    344}
    345
    346/**
    347 * sdw_intel_probe() - SoundWire Intel probe routine
    348 * @res: resource data
    349 *
    350 * This registers an auxiliary device for each Master handled by the controller,
    351 * and SoundWire Master and Slave devices will be created by the auxiliary
    352 * device probe. All the information necessary is stored in the context, and
    353 * the res argument pointer can be freed after this step.
    354 * This function will be called after sdw_intel_acpi_scan() by SOF probe.
    355 */
    356struct sdw_intel_ctx
    357*sdw_intel_probe(struct sdw_intel_res *res)
    358{
    359	return sdw_intel_probe_controller(res);
    360}
    361EXPORT_SYMBOL_NS(sdw_intel_probe, SOUNDWIRE_INTEL_INIT);
    362
    363/**
    364 * sdw_intel_startup() - SoundWire Intel startup
    365 * @ctx: SoundWire context allocated in the probe
    366 *
    367 * Startup Intel SoundWire controller. This function will be called after
    368 * Intel Audio DSP is powered up.
    369 */
    370int sdw_intel_startup(struct sdw_intel_ctx *ctx)
    371{
    372	return sdw_intel_startup_controller(ctx);
    373}
    374EXPORT_SYMBOL_NS(sdw_intel_startup, SOUNDWIRE_INTEL_INIT);
    375/**
    376 * sdw_intel_exit() - SoundWire Intel exit
    377 * @ctx: SoundWire context allocated in the probe
    378 *
    379 * Delete the controller instances created and cleanup
    380 */
    381void sdw_intel_exit(struct sdw_intel_ctx *ctx)
    382{
    383	sdw_intel_cleanup(ctx);
    384	kfree(ctx->ids);
    385	kfree(ctx->ldev);
    386	kfree(ctx);
    387}
    388EXPORT_SYMBOL_NS(sdw_intel_exit, SOUNDWIRE_INTEL_INIT);
    389
    390void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx)
    391{
    392	struct sdw_intel_link_dev *ldev;
    393	u32 link_mask;
    394	int i;
    395
    396	if (!ctx->ldev)
    397		return;
    398
    399	link_mask = ctx->link_mask;
    400
    401	/* Startup SDW Master devices */
    402	for (i = 0; i < ctx->count; i++) {
    403		if (!(link_mask & BIT(i)))
    404			continue;
    405
    406		ldev = ctx->ldev[i];
    407
    408		intel_link_process_wakeen_event(&ldev->auxdev);
    409	}
    410}
    411EXPORT_SYMBOL_NS(sdw_intel_process_wakeen_event, SOUNDWIRE_INTEL_INIT);
    412
    413MODULE_LICENSE("Dual BSD/GPL");
    414MODULE_DESCRIPTION("Intel Soundwire Init Library");