Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Qualcomm Wireless Connectivity Subsystem Peripheral Image Loader
0004  *
0005  * Copyright (C) 2016 Linaro Ltd
0006  * Copyright (C) 2014 Sony Mobile Communications AB
0007  * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
0008  */
0009 
0010 #include <linux/clk.h>
0011 #include <linux/delay.h>
0012 #include <linux/firmware.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/io.h>
0017 #include <linux/of_address.h>
0018 #include <linux/of_device.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/pm_domain.h>
0021 #include <linux/pm_runtime.h>
0022 #include <linux/qcom_scm.h>
0023 #include <linux/regulator/consumer.h>
0024 #include <linux/remoteproc.h>
0025 #include <linux/soc/qcom/mdt_loader.h>
0026 #include <linux/soc/qcom/smem.h>
0027 #include <linux/soc/qcom/smem_state.h>
0028 
0029 #include "qcom_common.h"
0030 #include "remoteproc_internal.h"
0031 #include "qcom_pil_info.h"
0032 #include "qcom_wcnss.h"
0033 
0034 #define WCNSS_CRASH_REASON_SMEM     422
0035 #define WCNSS_FIRMWARE_NAME     "wcnss.mdt"
0036 #define WCNSS_PAS_ID            6
0037 #define WCNSS_SSCTL_ID          0x13
0038 
0039 #define WCNSS_SPARE_NVBIN_DLND      BIT(25)
0040 
0041 #define WCNSS_PMU_IRIS_XO_CFG       BIT(3)
0042 #define WCNSS_PMU_IRIS_XO_EN        BIT(4)
0043 #define WCNSS_PMU_GC_BUS_MUX_SEL_TOP    BIT(5)
0044 #define WCNSS_PMU_IRIS_XO_CFG_STS   BIT(6) /* 1: in progress, 0: done */
0045 
0046 #define WCNSS_PMU_IRIS_RESET        BIT(7)
0047 #define WCNSS_PMU_IRIS_RESET_STS    BIT(8) /* 1: in progress, 0: done */
0048 #define WCNSS_PMU_IRIS_XO_READ      BIT(9)
0049 #define WCNSS_PMU_IRIS_XO_READ_STS  BIT(10)
0050 
0051 #define WCNSS_PMU_XO_MODE_MASK      GENMASK(2, 1)
0052 #define WCNSS_PMU_XO_MODE_19p2      0
0053 #define WCNSS_PMU_XO_MODE_48        3
0054 
0055 #define WCNSS_MAX_PDS           2
0056 
0057 struct wcnss_data {
0058     size_t pmu_offset;
0059     size_t spare_offset;
0060 
0061     const char *pd_names[WCNSS_MAX_PDS];
0062     const struct wcnss_vreg_info *vregs;
0063     size_t num_vregs, num_pd_vregs;
0064 };
0065 
0066 struct qcom_wcnss {
0067     struct device *dev;
0068     struct rproc *rproc;
0069 
0070     void __iomem *pmu_cfg;
0071     void __iomem *spare_out;
0072 
0073     bool use_48mhz_xo;
0074 
0075     int wdog_irq;
0076     int fatal_irq;
0077     int ready_irq;
0078     int handover_irq;
0079     int stop_ack_irq;
0080 
0081     struct qcom_smem_state *state;
0082     unsigned stop_bit;
0083 
0084     struct mutex iris_lock;
0085     struct qcom_iris *iris;
0086 
0087     struct device *pds[WCNSS_MAX_PDS];
0088     size_t num_pds;
0089     struct regulator_bulk_data *vregs;
0090     size_t num_vregs;
0091 
0092     struct completion start_done;
0093     struct completion stop_done;
0094 
0095     phys_addr_t mem_phys;
0096     phys_addr_t mem_reloc;
0097     void *mem_region;
0098     size_t mem_size;
0099 
0100     struct qcom_rproc_subdev smd_subdev;
0101     struct qcom_sysmon *sysmon;
0102 };
0103 
0104 static const struct wcnss_data riva_data = {
0105     .pmu_offset = 0x28,
0106     .spare_offset = 0xb4,
0107 
0108     .vregs = (struct wcnss_vreg_info[]) {
0109         { "vddmx",  1050000, 1150000, 0 },
0110         { "vddcx",  1050000, 1150000, 0 },
0111         { "vddpx",  1800000, 1800000, 0 },
0112     },
0113     .num_vregs = 3,
0114 };
0115 
0116 static const struct wcnss_data pronto_v1_data = {
0117     .pmu_offset = 0x1004,
0118     .spare_offset = 0x1088,
0119 
0120     .pd_names = { "mx", "cx" },
0121     .vregs = (struct wcnss_vreg_info[]) {
0122         { "vddmx", 950000, 1150000, 0 },
0123         { "vddcx", .super_turbo = true},
0124         { "vddpx", 1800000, 1800000, 0 },
0125     },
0126     .num_pd_vregs = 2,
0127     .num_vregs = 1,
0128 };
0129 
0130 static const struct wcnss_data pronto_v2_data = {
0131     .pmu_offset = 0x1004,
0132     .spare_offset = 0x1088,
0133 
0134     .pd_names = { "mx", "cx" },
0135     .vregs = (struct wcnss_vreg_info[]) {
0136         { "vddmx", 1287500, 1287500, 0 },
0137         { "vddcx", .super_turbo = true },
0138         { "vddpx", 1800000, 1800000, 0 },
0139     },
0140     .num_pd_vregs = 2,
0141     .num_vregs = 1,
0142 };
0143 
0144 static int wcnss_load(struct rproc *rproc, const struct firmware *fw)
0145 {
0146     struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
0147     int ret;
0148 
0149     ret = qcom_mdt_load(wcnss->dev, fw, rproc->firmware, WCNSS_PAS_ID,
0150                 wcnss->mem_region, wcnss->mem_phys,
0151                 wcnss->mem_size, &wcnss->mem_reloc);
0152     if (ret)
0153         return ret;
0154 
0155     qcom_pil_info_store("wcnss", wcnss->mem_phys, wcnss->mem_size);
0156 
0157     return 0;
0158 }
0159 
0160 static void wcnss_indicate_nv_download(struct qcom_wcnss *wcnss)
0161 {
0162     u32 val;
0163 
0164     /* Indicate NV download capability */
0165     val = readl(wcnss->spare_out);
0166     val |= WCNSS_SPARE_NVBIN_DLND;
0167     writel(val, wcnss->spare_out);
0168 }
0169 
0170 static void wcnss_configure_iris(struct qcom_wcnss *wcnss)
0171 {
0172     u32 val;
0173 
0174     /* Clear PMU cfg register */
0175     writel(0, wcnss->pmu_cfg);
0176 
0177     val = WCNSS_PMU_GC_BUS_MUX_SEL_TOP | WCNSS_PMU_IRIS_XO_EN;
0178     writel(val, wcnss->pmu_cfg);
0179 
0180     /* Clear XO_MODE */
0181     val &= ~WCNSS_PMU_XO_MODE_MASK;
0182     if (wcnss->use_48mhz_xo)
0183         val |= WCNSS_PMU_XO_MODE_48 << 1;
0184     else
0185         val |= WCNSS_PMU_XO_MODE_19p2 << 1;
0186     writel(val, wcnss->pmu_cfg);
0187 
0188     /* Reset IRIS */
0189     val |= WCNSS_PMU_IRIS_RESET;
0190     writel(val, wcnss->pmu_cfg);
0191 
0192     /* Wait for PMU.iris_reg_reset_sts */
0193     while (readl(wcnss->pmu_cfg) & WCNSS_PMU_IRIS_RESET_STS)
0194         cpu_relax();
0195 
0196     /* Clear IRIS reset */
0197     val &= ~WCNSS_PMU_IRIS_RESET;
0198     writel(val, wcnss->pmu_cfg);
0199 
0200     /* Start IRIS XO configuration */
0201     val |= WCNSS_PMU_IRIS_XO_CFG;
0202     writel(val, wcnss->pmu_cfg);
0203 
0204     /* Wait for XO configuration to finish */
0205     while (readl(wcnss->pmu_cfg) & WCNSS_PMU_IRIS_XO_CFG_STS)
0206         cpu_relax();
0207 
0208     /* Stop IRIS XO configuration */
0209     val &= ~WCNSS_PMU_GC_BUS_MUX_SEL_TOP;
0210     val &= ~WCNSS_PMU_IRIS_XO_CFG;
0211     writel(val, wcnss->pmu_cfg);
0212 
0213     /* Add some delay for XO to settle */
0214     msleep(20);
0215 }
0216 
0217 static int wcnss_start(struct rproc *rproc)
0218 {
0219     struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
0220     int ret, i;
0221 
0222     mutex_lock(&wcnss->iris_lock);
0223     if (!wcnss->iris) {
0224         dev_err(wcnss->dev, "no iris registered\n");
0225         ret = -EINVAL;
0226         goto release_iris_lock;
0227     }
0228 
0229     for (i = 0; i < wcnss->num_pds; i++) {
0230         dev_pm_genpd_set_performance_state(wcnss->pds[i], INT_MAX);
0231         ret = pm_runtime_get_sync(wcnss->pds[i]);
0232         if (ret < 0) {
0233             pm_runtime_put_noidle(wcnss->pds[i]);
0234             goto disable_pds;
0235         }
0236     }
0237 
0238     ret = regulator_bulk_enable(wcnss->num_vregs, wcnss->vregs);
0239     if (ret)
0240         goto disable_pds;
0241 
0242     ret = qcom_iris_enable(wcnss->iris);
0243     if (ret)
0244         goto disable_regulators;
0245 
0246     wcnss_indicate_nv_download(wcnss);
0247     wcnss_configure_iris(wcnss);
0248 
0249     ret = qcom_scm_pas_auth_and_reset(WCNSS_PAS_ID);
0250     if (ret) {
0251         dev_err(wcnss->dev,
0252             "failed to authenticate image and release reset\n");
0253         goto disable_iris;
0254     }
0255 
0256     ret = wait_for_completion_timeout(&wcnss->start_done,
0257                       msecs_to_jiffies(5000));
0258     if (wcnss->ready_irq > 0 && ret == 0) {
0259         /* We have a ready_irq, but it didn't fire in time. */
0260         dev_err(wcnss->dev, "start timed out\n");
0261         qcom_scm_pas_shutdown(WCNSS_PAS_ID);
0262         ret = -ETIMEDOUT;
0263         goto disable_iris;
0264     }
0265 
0266     ret = 0;
0267 
0268 disable_iris:
0269     qcom_iris_disable(wcnss->iris);
0270 disable_regulators:
0271     regulator_bulk_disable(wcnss->num_vregs, wcnss->vregs);
0272 disable_pds:
0273     for (i--; i >= 0; i--) {
0274         pm_runtime_put(wcnss->pds[i]);
0275         dev_pm_genpd_set_performance_state(wcnss->pds[i], 0);
0276     }
0277 release_iris_lock:
0278     mutex_unlock(&wcnss->iris_lock);
0279 
0280     return ret;
0281 }
0282 
0283 static int wcnss_stop(struct rproc *rproc)
0284 {
0285     struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
0286     int ret;
0287 
0288     if (wcnss->state) {
0289         qcom_smem_state_update_bits(wcnss->state,
0290                         BIT(wcnss->stop_bit),
0291                         BIT(wcnss->stop_bit));
0292 
0293         ret = wait_for_completion_timeout(&wcnss->stop_done,
0294                           msecs_to_jiffies(5000));
0295         if (ret == 0)
0296             dev_err(wcnss->dev, "timed out on wait\n");
0297 
0298         qcom_smem_state_update_bits(wcnss->state,
0299                         BIT(wcnss->stop_bit),
0300                         0);
0301     }
0302 
0303     ret = qcom_scm_pas_shutdown(WCNSS_PAS_ID);
0304     if (ret)
0305         dev_err(wcnss->dev, "failed to shutdown: %d\n", ret);
0306 
0307     return ret;
0308 }
0309 
0310 static void *wcnss_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
0311 {
0312     struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
0313     int offset;
0314 
0315     offset = da - wcnss->mem_reloc;
0316     if (offset < 0 || offset + len > wcnss->mem_size)
0317         return NULL;
0318 
0319     return wcnss->mem_region + offset;
0320 }
0321 
0322 static const struct rproc_ops wcnss_ops = {
0323     .start = wcnss_start,
0324     .stop = wcnss_stop,
0325     .da_to_va = wcnss_da_to_va,
0326     .parse_fw = qcom_register_dump_segments,
0327     .load = wcnss_load,
0328 };
0329 
0330 static irqreturn_t wcnss_wdog_interrupt(int irq, void *dev)
0331 {
0332     struct qcom_wcnss *wcnss = dev;
0333 
0334     rproc_report_crash(wcnss->rproc, RPROC_WATCHDOG);
0335 
0336     return IRQ_HANDLED;
0337 }
0338 
0339 static irqreturn_t wcnss_fatal_interrupt(int irq, void *dev)
0340 {
0341     struct qcom_wcnss *wcnss = dev;
0342     size_t len;
0343     char *msg;
0344 
0345     msg = qcom_smem_get(QCOM_SMEM_HOST_ANY, WCNSS_CRASH_REASON_SMEM, &len);
0346     if (!IS_ERR(msg) && len > 0 && msg[0])
0347         dev_err(wcnss->dev, "fatal error received: %s\n", msg);
0348 
0349     rproc_report_crash(wcnss->rproc, RPROC_FATAL_ERROR);
0350 
0351     return IRQ_HANDLED;
0352 }
0353 
0354 static irqreturn_t wcnss_ready_interrupt(int irq, void *dev)
0355 {
0356     struct qcom_wcnss *wcnss = dev;
0357 
0358     complete(&wcnss->start_done);
0359 
0360     return IRQ_HANDLED;
0361 }
0362 
0363 static irqreturn_t wcnss_handover_interrupt(int irq, void *dev)
0364 {
0365     /*
0366      * XXX: At this point we're supposed to release the resources that we
0367      * have been holding on behalf of the WCNSS. Unfortunately this
0368      * interrupt comes way before the other side seems to be done.
0369      *
0370      * So we're currently relying on the ready interrupt firing later then
0371      * this and we just disable the resources at the end of wcnss_start().
0372      */
0373 
0374     return IRQ_HANDLED;
0375 }
0376 
0377 static irqreturn_t wcnss_stop_ack_interrupt(int irq, void *dev)
0378 {
0379     struct qcom_wcnss *wcnss = dev;
0380 
0381     complete(&wcnss->stop_done);
0382 
0383     return IRQ_HANDLED;
0384 }
0385 
0386 static int wcnss_init_pds(struct qcom_wcnss *wcnss,
0387               const char * const pd_names[WCNSS_MAX_PDS])
0388 {
0389     int i, ret;
0390 
0391     for (i = 0; i < WCNSS_MAX_PDS; i++) {
0392         if (!pd_names[i])
0393             break;
0394 
0395         wcnss->pds[i] = dev_pm_domain_attach_by_name(wcnss->dev, pd_names[i]);
0396         if (IS_ERR_OR_NULL(wcnss->pds[i])) {
0397             ret = PTR_ERR(wcnss->pds[i]) ? : -ENODATA;
0398             for (i--; i >= 0; i--)
0399                 dev_pm_domain_detach(wcnss->pds[i], false);
0400             return ret;
0401         }
0402     }
0403     wcnss->num_pds = i;
0404 
0405     return 0;
0406 }
0407 
0408 static void wcnss_release_pds(struct qcom_wcnss *wcnss)
0409 {
0410     int i;
0411 
0412     for (i = 0; i < wcnss->num_pds; i++)
0413         dev_pm_domain_detach(wcnss->pds[i], false);
0414 }
0415 
0416 static int wcnss_init_regulators(struct qcom_wcnss *wcnss,
0417                  const struct wcnss_vreg_info *info,
0418                  int num_vregs, int num_pd_vregs)
0419 {
0420     struct regulator_bulk_data *bulk;
0421     int ret;
0422     int i;
0423 
0424     /*
0425      * If attaching the power domains suceeded we can skip requesting
0426      * the regulators for the power domains. For old device trees we need to
0427      * reserve extra space to manage them through the regulator interface.
0428      */
0429     if (wcnss->num_pds)
0430         info += num_pd_vregs;
0431     else
0432         num_vregs += num_pd_vregs;
0433 
0434     bulk = devm_kcalloc(wcnss->dev,
0435                 num_vregs, sizeof(struct regulator_bulk_data),
0436                 GFP_KERNEL);
0437     if (!bulk)
0438         return -ENOMEM;
0439 
0440     for (i = 0; i < num_vregs; i++)
0441         bulk[i].supply = info[i].name;
0442 
0443     ret = devm_regulator_bulk_get(wcnss->dev, num_vregs, bulk);
0444     if (ret)
0445         return ret;
0446 
0447     for (i = 0; i < num_vregs; i++) {
0448         if (info[i].max_voltage)
0449             regulator_set_voltage(bulk[i].consumer,
0450                           info[i].min_voltage,
0451                           info[i].max_voltage);
0452 
0453         if (info[i].load_uA)
0454             regulator_set_load(bulk[i].consumer, info[i].load_uA);
0455     }
0456 
0457     wcnss->vregs = bulk;
0458     wcnss->num_vregs = num_vregs;
0459 
0460     return 0;
0461 }
0462 
0463 static int wcnss_request_irq(struct qcom_wcnss *wcnss,
0464                  struct platform_device *pdev,
0465                  const char *name,
0466                  bool optional,
0467                  irq_handler_t thread_fn)
0468 {
0469     int ret;
0470     int irq_number;
0471 
0472     ret = platform_get_irq_byname(pdev, name);
0473     if (ret < 0 && optional) {
0474         dev_dbg(&pdev->dev, "no %s IRQ defined, ignoring\n", name);
0475         return 0;
0476     } else if (ret < 0) {
0477         dev_err(&pdev->dev, "no %s IRQ defined\n", name);
0478         return ret;
0479     }
0480 
0481     irq_number = ret;
0482 
0483     ret = devm_request_threaded_irq(&pdev->dev, ret,
0484                     NULL, thread_fn,
0485                     IRQF_TRIGGER_RISING | IRQF_ONESHOT,
0486                     "wcnss", wcnss);
0487     if (ret) {
0488         dev_err(&pdev->dev, "request %s IRQ failed\n", name);
0489         return ret;
0490     }
0491 
0492     /* Return the IRQ number if the IRQ was successfully acquired */
0493     return irq_number;
0494 }
0495 
0496 static int wcnss_alloc_memory_region(struct qcom_wcnss *wcnss)
0497 {
0498     struct device_node *node;
0499     struct resource r;
0500     int ret;
0501 
0502     node = of_parse_phandle(wcnss->dev->of_node, "memory-region", 0);
0503     if (!node) {
0504         dev_err(wcnss->dev, "no memory-region specified\n");
0505         return -EINVAL;
0506     }
0507 
0508     ret = of_address_to_resource(node, 0, &r);
0509     of_node_put(node);
0510     if (ret)
0511         return ret;
0512 
0513     wcnss->mem_phys = wcnss->mem_reloc = r.start;
0514     wcnss->mem_size = resource_size(&r);
0515     wcnss->mem_region = devm_ioremap_wc(wcnss->dev, wcnss->mem_phys, wcnss->mem_size);
0516     if (!wcnss->mem_region) {
0517         dev_err(wcnss->dev, "unable to map memory region: %pa+%zx\n",
0518             &r.start, wcnss->mem_size);
0519         return -EBUSY;
0520     }
0521 
0522     return 0;
0523 }
0524 
0525 static int wcnss_probe(struct platform_device *pdev)
0526 {
0527     const char *fw_name = WCNSS_FIRMWARE_NAME;
0528     const struct wcnss_data *data;
0529     struct qcom_wcnss *wcnss;
0530     struct resource *res;
0531     struct rproc *rproc;
0532     void __iomem *mmio;
0533     int ret;
0534 
0535     data = of_device_get_match_data(&pdev->dev);
0536 
0537     if (!qcom_scm_is_available())
0538         return -EPROBE_DEFER;
0539 
0540     if (!qcom_scm_pas_supported(WCNSS_PAS_ID)) {
0541         dev_err(&pdev->dev, "PAS is not available for WCNSS\n");
0542         return -ENXIO;
0543     }
0544 
0545     ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
0546                       &fw_name);
0547     if (ret < 0 && ret != -EINVAL)
0548         return ret;
0549 
0550     rproc = rproc_alloc(&pdev->dev, pdev->name, &wcnss_ops,
0551                 fw_name, sizeof(*wcnss));
0552     if (!rproc) {
0553         dev_err(&pdev->dev, "unable to allocate remoteproc\n");
0554         return -ENOMEM;
0555     }
0556     rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
0557 
0558     wcnss = (struct qcom_wcnss *)rproc->priv;
0559     wcnss->dev = &pdev->dev;
0560     wcnss->rproc = rproc;
0561     platform_set_drvdata(pdev, wcnss);
0562 
0563     init_completion(&wcnss->start_done);
0564     init_completion(&wcnss->stop_done);
0565 
0566     mutex_init(&wcnss->iris_lock);
0567 
0568     res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pmu");
0569     mmio = devm_ioremap_resource(&pdev->dev, res);
0570     if (IS_ERR(mmio)) {
0571         ret = PTR_ERR(mmio);
0572         goto free_rproc;
0573     }
0574 
0575     ret = wcnss_alloc_memory_region(wcnss);
0576     if (ret)
0577         goto free_rproc;
0578 
0579     wcnss->pmu_cfg = mmio + data->pmu_offset;
0580     wcnss->spare_out = mmio + data->spare_offset;
0581 
0582     /*
0583      * We might need to fallback to regulators instead of power domains
0584      * for old device trees. Don't report an error in that case.
0585      */
0586     ret = wcnss_init_pds(wcnss, data->pd_names);
0587     if (ret && (ret != -ENODATA || !data->num_pd_vregs))
0588         goto free_rproc;
0589 
0590     ret = wcnss_init_regulators(wcnss, data->vregs, data->num_vregs,
0591                     data->num_pd_vregs);
0592     if (ret)
0593         goto detach_pds;
0594 
0595     ret = wcnss_request_irq(wcnss, pdev, "wdog", false, wcnss_wdog_interrupt);
0596     if (ret < 0)
0597         goto detach_pds;
0598     wcnss->wdog_irq = ret;
0599 
0600     ret = wcnss_request_irq(wcnss, pdev, "fatal", false, wcnss_fatal_interrupt);
0601     if (ret < 0)
0602         goto detach_pds;
0603     wcnss->fatal_irq = ret;
0604 
0605     ret = wcnss_request_irq(wcnss, pdev, "ready", true, wcnss_ready_interrupt);
0606     if (ret < 0)
0607         goto detach_pds;
0608     wcnss->ready_irq = ret;
0609 
0610     ret = wcnss_request_irq(wcnss, pdev, "handover", true, wcnss_handover_interrupt);
0611     if (ret < 0)
0612         goto detach_pds;
0613     wcnss->handover_irq = ret;
0614 
0615     ret = wcnss_request_irq(wcnss, pdev, "stop-ack", true, wcnss_stop_ack_interrupt);
0616     if (ret < 0)
0617         goto detach_pds;
0618     wcnss->stop_ack_irq = ret;
0619 
0620     if (wcnss->stop_ack_irq) {
0621         wcnss->state = devm_qcom_smem_state_get(&pdev->dev, "stop",
0622                             &wcnss->stop_bit);
0623         if (IS_ERR(wcnss->state)) {
0624             ret = PTR_ERR(wcnss->state);
0625             goto detach_pds;
0626         }
0627     }
0628 
0629     qcom_add_smd_subdev(rproc, &wcnss->smd_subdev);
0630     wcnss->sysmon = qcom_add_sysmon_subdev(rproc, "wcnss", WCNSS_SSCTL_ID);
0631     if (IS_ERR(wcnss->sysmon)) {
0632         ret = PTR_ERR(wcnss->sysmon);
0633         goto detach_pds;
0634     }
0635 
0636     wcnss->iris = qcom_iris_probe(&pdev->dev, &wcnss->use_48mhz_xo);
0637     if (IS_ERR(wcnss->iris)) {
0638         ret = PTR_ERR(wcnss->iris);
0639         goto detach_pds;
0640     }
0641 
0642     ret = rproc_add(rproc);
0643     if (ret)
0644         goto remove_iris;
0645 
0646     return 0;
0647 
0648 remove_iris:
0649     qcom_iris_remove(wcnss->iris);
0650 detach_pds:
0651     wcnss_release_pds(wcnss);
0652 free_rproc:
0653     rproc_free(rproc);
0654 
0655     return ret;
0656 }
0657 
0658 static int wcnss_remove(struct platform_device *pdev)
0659 {
0660     struct qcom_wcnss *wcnss = platform_get_drvdata(pdev);
0661 
0662     qcom_iris_remove(wcnss->iris);
0663 
0664     rproc_del(wcnss->rproc);
0665 
0666     qcom_remove_sysmon_subdev(wcnss->sysmon);
0667     qcom_remove_smd_subdev(wcnss->rproc, &wcnss->smd_subdev);
0668     wcnss_release_pds(wcnss);
0669     rproc_free(wcnss->rproc);
0670 
0671     return 0;
0672 }
0673 
0674 static const struct of_device_id wcnss_of_match[] = {
0675     { .compatible = "qcom,riva-pil", &riva_data },
0676     { .compatible = "qcom,pronto-v1-pil", &pronto_v1_data },
0677     { .compatible = "qcom,pronto-v2-pil", &pronto_v2_data },
0678     { },
0679 };
0680 MODULE_DEVICE_TABLE(of, wcnss_of_match);
0681 
0682 static struct platform_driver wcnss_driver = {
0683     .probe = wcnss_probe,
0684     .remove = wcnss_remove,
0685     .driver = {
0686         .name = "qcom-wcnss-pil",
0687         .of_match_table = wcnss_of_match,
0688     },
0689 };
0690 
0691 module_platform_driver(wcnss_driver);
0692 
0693 MODULE_DESCRIPTION("Qualcomm Peripheral Image Loader for Wireless Subsystem");
0694 MODULE_LICENSE("GPL v2");