Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
0002 // Copyright(c) 2015-17 Intel Corporation.
0003 
0004 /*
0005  * SDW Intel Init Routines
0006  *
0007  * Initializes and creates SDW devices based on ACPI and Hardware values
0008  */
0009 
0010 #include <linux/acpi.h>
0011 #include <linux/export.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/io.h>
0014 #include <linux/module.h>
0015 #include <linux/auxiliary_bus.h>
0016 #include <linux/pm_runtime.h>
0017 #include <linux/soundwire/sdw_intel.h>
0018 #include "cadence_master.h"
0019 #include "intel.h"
0020 
0021 static void intel_link_dev_release(struct device *dev)
0022 {
0023     struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
0024     struct sdw_intel_link_dev *ldev = auxiliary_dev_to_sdw_intel_link_dev(auxdev);
0025 
0026     kfree(ldev);
0027 }
0028 
0029 /* alloc, init and add link devices */
0030 static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res *res,
0031                               struct sdw_intel_ctx *ctx,
0032                               struct fwnode_handle *fwnode,
0033                               const char *name,
0034                               int link_id)
0035 {
0036     struct sdw_intel_link_dev *ldev;
0037     struct sdw_intel_link_res *link;
0038     struct auxiliary_device *auxdev;
0039     int ret;
0040 
0041     ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
0042     if (!ldev)
0043         return ERR_PTR(-ENOMEM);
0044 
0045     auxdev = &ldev->auxdev;
0046     auxdev->name = name;
0047     auxdev->dev.parent = res->parent;
0048     auxdev->dev.fwnode = fwnode;
0049     auxdev->dev.release = intel_link_dev_release;
0050 
0051     /* we don't use an IDA since we already have a link ID */
0052     auxdev->id = link_id;
0053 
0054     /*
0055      * keep a handle on the allocated memory, to be used in all other functions.
0056      * Since the same pattern is used to skip links that are not enabled, there is
0057      * no need to check if ctx->ldev[i] is NULL later on.
0058      */
0059     ctx->ldev[link_id] = ldev;
0060 
0061     /* Add link information used in the driver probe */
0062     link = &ldev->link_res;
0063     link->mmio_base = res->mmio_base;
0064     link->registers = res->mmio_base + SDW_LINK_BASE
0065         + (SDW_LINK_SIZE * link_id);
0066     link->shim = res->mmio_base + res->shim_base;
0067     link->alh = res->mmio_base + res->alh_base;
0068 
0069     link->ops = res->ops;
0070     link->dev = res->dev;
0071 
0072     link->clock_stop_quirks = res->clock_stop_quirks;
0073     link->shim_lock = &ctx->shim_lock;
0074     link->shim_mask = &ctx->shim_mask;
0075     link->link_mask = ctx->link_mask;
0076 
0077     /* now follow the two-step init/add sequence */
0078     ret = auxiliary_device_init(auxdev);
0079     if (ret < 0) {
0080         dev_err(res->parent, "failed to initialize link dev %s link_id %d\n",
0081             name, link_id);
0082         kfree(ldev);
0083         return ERR_PTR(ret);
0084     }
0085 
0086     ret = auxiliary_device_add(&ldev->auxdev);
0087     if (ret < 0) {
0088         dev_err(res->parent, "failed to add link dev %s link_id %d\n",
0089             ldev->auxdev.name, link_id);
0090         /* ldev will be freed with the put_device() and .release sequence */
0091         auxiliary_device_uninit(&ldev->auxdev);
0092         return ERR_PTR(ret);
0093     }
0094 
0095     return ldev;
0096 }
0097 
0098 static void intel_link_dev_unregister(struct sdw_intel_link_dev *ldev)
0099 {
0100     auxiliary_device_delete(&ldev->auxdev);
0101     auxiliary_device_uninit(&ldev->auxdev);
0102 }
0103 
0104 static int sdw_intel_cleanup(struct sdw_intel_ctx *ctx)
0105 {
0106     struct sdw_intel_link_dev *ldev;
0107     u32 link_mask;
0108     int i;
0109 
0110     link_mask = ctx->link_mask;
0111 
0112     for (i = 0; i < ctx->count; i++) {
0113         if (!(link_mask & BIT(i)))
0114             continue;
0115 
0116         ldev = ctx->ldev[i];
0117 
0118         pm_runtime_disable(&ldev->auxdev.dev);
0119         if (!ldev->link_res.clock_stop_quirks)
0120             pm_runtime_put_noidle(ldev->link_res.dev);
0121 
0122         intel_link_dev_unregister(ldev);
0123     }
0124 
0125     return 0;
0126 }
0127 
0128 #define HDA_DSP_REG_ADSPIC2             (0x10)
0129 #define HDA_DSP_REG_ADSPIS2             (0x14)
0130 #define HDA_DSP_REG_ADSPIC2_SNDW        BIT(5)
0131 
0132 /**
0133  * sdw_intel_enable_irq() - enable/disable Intel SoundWire IRQ
0134  * @mmio_base: The mmio base of the control register
0135  * @enable: true if enable
0136  */
0137 void sdw_intel_enable_irq(void __iomem *mmio_base, bool enable)
0138 {
0139     u32 val;
0140 
0141     val = readl(mmio_base + HDA_DSP_REG_ADSPIC2);
0142 
0143     if (enable)
0144         val |= HDA_DSP_REG_ADSPIC2_SNDW;
0145     else
0146         val &= ~HDA_DSP_REG_ADSPIC2_SNDW;
0147 
0148     writel(val, mmio_base + HDA_DSP_REG_ADSPIC2);
0149 }
0150 EXPORT_SYMBOL_NS(sdw_intel_enable_irq, SOUNDWIRE_INTEL_INIT);
0151 
0152 irqreturn_t sdw_intel_thread(int irq, void *dev_id)
0153 {
0154     struct sdw_intel_ctx *ctx = dev_id;
0155     struct sdw_intel_link_res *link;
0156 
0157     list_for_each_entry(link, &ctx->link_list, list)
0158         sdw_cdns_irq(irq, link->cdns);
0159 
0160     sdw_intel_enable_irq(ctx->mmio_base, true);
0161     return IRQ_HANDLED;
0162 }
0163 EXPORT_SYMBOL_NS(sdw_intel_thread, SOUNDWIRE_INTEL_INIT);
0164 
0165 static struct sdw_intel_ctx
0166 *sdw_intel_probe_controller(struct sdw_intel_res *res)
0167 {
0168     struct sdw_intel_link_res *link;
0169     struct sdw_intel_link_dev *ldev;
0170     struct sdw_intel_ctx *ctx;
0171     struct acpi_device *adev;
0172     struct sdw_slave *slave;
0173     struct list_head *node;
0174     struct sdw_bus *bus;
0175     u32 link_mask;
0176     int num_slaves = 0;
0177     int count;
0178     int i;
0179 
0180     if (!res)
0181         return NULL;
0182 
0183     adev = acpi_fetch_acpi_dev(res->handle);
0184     if (!adev)
0185         return NULL;
0186 
0187     if (!res->count)
0188         return NULL;
0189 
0190     count = res->count;
0191     dev_dbg(&adev->dev, "Creating %d SDW Link devices\n", count);
0192 
0193     /*
0194      * we need to alloc/free memory manually and can't use devm:
0195      * this routine may be called from a workqueue, and not from
0196      * the parent .probe.
0197      * If devm_ was used, the memory might never be freed on errors.
0198      */
0199     ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
0200     if (!ctx)
0201         return NULL;
0202 
0203     ctx->count = count;
0204 
0205     /*
0206      * allocate the array of pointers. The link-specific data is allocated
0207      * as part of the first loop below and released with the auxiliary_device_uninit().
0208      * If some links are disabled, the link pointer will remain NULL. Given that the
0209      * number of links is small, this is simpler than using a list to keep track of links.
0210      */
0211     ctx->ldev = kcalloc(ctx->count, sizeof(*ctx->ldev), GFP_KERNEL);
0212     if (!ctx->ldev) {
0213         kfree(ctx);
0214         return NULL;
0215     }
0216 
0217     ctx->mmio_base = res->mmio_base;
0218     ctx->shim_base = res->shim_base;
0219     ctx->alh_base = res->alh_base;
0220     ctx->link_mask = res->link_mask;
0221     ctx->handle = res->handle;
0222     mutex_init(&ctx->shim_lock);
0223 
0224     link_mask = ctx->link_mask;
0225 
0226     INIT_LIST_HEAD(&ctx->link_list);
0227 
0228     for (i = 0; i < count; i++) {
0229         if (!(link_mask & BIT(i)))
0230             continue;
0231 
0232         /*
0233          * init and add a device for each link
0234          *
0235          * The name of the device will be soundwire_intel.link.[i],
0236          * with the "soundwire_intel" module prefix automatically added
0237          * by the auxiliary bus core.
0238          */
0239         ldev = intel_link_dev_register(res,
0240                            ctx,
0241                            acpi_fwnode_handle(adev),
0242                            "link",
0243                            i);
0244         if (IS_ERR(ldev))
0245             goto err;
0246 
0247         link = &ldev->link_res;
0248         link->cdns = auxiliary_get_drvdata(&ldev->auxdev);
0249 
0250         if (!link->cdns) {
0251             dev_err(&adev->dev, "failed to get link->cdns\n");
0252             /*
0253              * 1 will be subtracted from i in the err label, but we need to call
0254              * intel_link_dev_unregister for this ldev, so plus 1 now
0255              */
0256             i++;
0257             goto err;
0258         }
0259         list_add_tail(&link->list, &ctx->link_list);
0260         bus = &link->cdns->bus;
0261         /* Calculate number of slaves */
0262         list_for_each(node, &bus->slaves)
0263             num_slaves++;
0264     }
0265 
0266     ctx->ids = kcalloc(num_slaves, sizeof(*ctx->ids), GFP_KERNEL);
0267     if (!ctx->ids)
0268         goto err;
0269 
0270     ctx->num_slaves = num_slaves;
0271     i = 0;
0272     list_for_each_entry(link, &ctx->link_list, list) {
0273         bus = &link->cdns->bus;
0274         list_for_each_entry(slave, &bus->slaves, node) {
0275             ctx->ids[i].id = slave->id;
0276             ctx->ids[i].link_id = bus->link_id;
0277             i++;
0278         }
0279     }
0280 
0281     return ctx;
0282 
0283 err:
0284     while (i--) {
0285         if (!(link_mask & BIT(i)))
0286             continue;
0287         ldev = ctx->ldev[i];
0288         intel_link_dev_unregister(ldev);
0289     }
0290     kfree(ctx->ldev);
0291     kfree(ctx);
0292     return NULL;
0293 }
0294 
0295 static int
0296 sdw_intel_startup_controller(struct sdw_intel_ctx *ctx)
0297 {
0298     struct acpi_device *adev = acpi_fetch_acpi_dev(ctx->handle);
0299     struct sdw_intel_link_dev *ldev;
0300     u32 caps;
0301     u32 link_mask;
0302     int i;
0303 
0304     if (!adev)
0305         return -EINVAL;
0306 
0307     /* Check SNDWLCAP.LCOUNT */
0308     caps = ioread32(ctx->mmio_base + ctx->shim_base + SDW_SHIM_LCAP);
0309     caps &= GENMASK(2, 0);
0310 
0311     /* Check HW supported vs property value */
0312     if (caps < ctx->count) {
0313         dev_err(&adev->dev,
0314             "BIOS master count is larger than hardware capabilities\n");
0315         return -EINVAL;
0316     }
0317 
0318     if (!ctx->ldev)
0319         return -EINVAL;
0320 
0321     link_mask = ctx->link_mask;
0322 
0323     /* Startup SDW Master devices */
0324     for (i = 0; i < ctx->count; i++) {
0325         if (!(link_mask & BIT(i)))
0326             continue;
0327 
0328         ldev = ctx->ldev[i];
0329 
0330         intel_link_startup(&ldev->auxdev);
0331 
0332         if (!ldev->link_res.clock_stop_quirks) {
0333             /*
0334              * we need to prevent the parent PCI device
0335              * from entering pm_runtime suspend, so that
0336              * power rails to the SoundWire IP are not
0337              * turned off.
0338              */
0339             pm_runtime_get_noresume(ldev->link_res.dev);
0340         }
0341     }
0342 
0343     return 0;
0344 }
0345 
0346 /**
0347  * sdw_intel_probe() - SoundWire Intel probe routine
0348  * @res: resource data
0349  *
0350  * This registers an auxiliary device for each Master handled by the controller,
0351  * and SoundWire Master and Slave devices will be created by the auxiliary
0352  * device probe. All the information necessary is stored in the context, and
0353  * the res argument pointer can be freed after this step.
0354  * This function will be called after sdw_intel_acpi_scan() by SOF probe.
0355  */
0356 struct sdw_intel_ctx
0357 *sdw_intel_probe(struct sdw_intel_res *res)
0358 {
0359     return sdw_intel_probe_controller(res);
0360 }
0361 EXPORT_SYMBOL_NS(sdw_intel_probe, SOUNDWIRE_INTEL_INIT);
0362 
0363 /**
0364  * sdw_intel_startup() - SoundWire Intel startup
0365  * @ctx: SoundWire context allocated in the probe
0366  *
0367  * Startup Intel SoundWire controller. This function will be called after
0368  * Intel Audio DSP is powered up.
0369  */
0370 int sdw_intel_startup(struct sdw_intel_ctx *ctx)
0371 {
0372     return sdw_intel_startup_controller(ctx);
0373 }
0374 EXPORT_SYMBOL_NS(sdw_intel_startup, SOUNDWIRE_INTEL_INIT);
0375 /**
0376  * sdw_intel_exit() - SoundWire Intel exit
0377  * @ctx: SoundWire context allocated in the probe
0378  *
0379  * Delete the controller instances created and cleanup
0380  */
0381 void sdw_intel_exit(struct sdw_intel_ctx *ctx)
0382 {
0383     sdw_intel_cleanup(ctx);
0384     kfree(ctx->ids);
0385     kfree(ctx->ldev);
0386     kfree(ctx);
0387 }
0388 EXPORT_SYMBOL_NS(sdw_intel_exit, SOUNDWIRE_INTEL_INIT);
0389 
0390 void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx)
0391 {
0392     struct sdw_intel_link_dev *ldev;
0393     u32 link_mask;
0394     int i;
0395 
0396     if (!ctx->ldev)
0397         return;
0398 
0399     link_mask = ctx->link_mask;
0400 
0401     /* Startup SDW Master devices */
0402     for (i = 0; i < ctx->count; i++) {
0403         if (!(link_mask & BIT(i)))
0404             continue;
0405 
0406         ldev = ctx->ldev[i];
0407 
0408         intel_link_process_wakeen_event(&ldev->auxdev);
0409     }
0410 }
0411 EXPORT_SYMBOL_NS(sdw_intel_process_wakeen_event, SOUNDWIRE_INTEL_INIT);
0412 
0413 MODULE_LICENSE("Dual BSD/GPL");
0414 MODULE_DESCRIPTION("Intel Soundwire Init Library");