bus: mhi: host: Move IRQ allocation to controller registration phase
[linux-2.6-microblaze.git] / drivers / bus / mhi / host / init.c
index a665b8e..bf672de 100644 (file)
@@ -86,7 +86,7 @@ static ssize_t serial_number_show(struct device *dev,
        struct mhi_device *mhi_dev = to_mhi_device(dev);
        struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
 
-       return snprintf(buf, PAGE_SIZE, "Serial Number: %u\n",
+       return sysfs_emit(buf, "Serial Number: %u\n",
                        mhi_cntrl->serial_number);
 }
 static DEVICE_ATTR_RO(serial_number);
@@ -100,17 +100,30 @@ static ssize_t oem_pk_hash_show(struct device *dev,
        int i, cnt = 0;
 
        for (i = 0; i < ARRAY_SIZE(mhi_cntrl->oem_pk_hash); i++)
-               cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
-                               "OEMPKHASH[%d]: 0x%x\n", i,
-                               mhi_cntrl->oem_pk_hash[i]);
+               cnt += sysfs_emit_at(buf, cnt, "OEMPKHASH[%d]: 0x%x\n",
+                               i, mhi_cntrl->oem_pk_hash[i]);
 
        return cnt;
 }
 static DEVICE_ATTR_RO(oem_pk_hash);
 
+static ssize_t soc_reset_store(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buf,
+                              size_t count)
+{
+       struct mhi_device *mhi_dev = to_mhi_device(dev);
+       struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
+
+       mhi_soc_reset(mhi_cntrl);
+       return count;
+}
+static DEVICE_ATTR_WO(soc_reset);
+
 static struct attribute *mhi_dev_attrs[] = {
        &dev_attr_serial_number.attr,
        &dev_attr_oem_pk_hash.attr,
+       &dev_attr_soc_reset.attr,
        NULL,
 };
 ATTRIBUTE_GROUPS(mhi_dev);
@@ -165,6 +178,12 @@ int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl)
                                   "bhi", mhi_cntrl);
        if (ret)
                return ret;
+       /*
+        * IRQs should be enabled during mhi_async_power_up(), so disable them explicitly here.
+        * Due to the use of IRQF_SHARED flag as default while requesting IRQs, we assume that
+        * IRQ_NOAUTOEN is not applicable.
+        */
+       disable_irq(mhi_cntrl->irq[0]);
 
        for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) {
                if (mhi_event->offload_ev)
@@ -186,6 +205,8 @@ int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl)
                                mhi_cntrl->irq[mhi_event->irq], i);
                        goto error_request;
                }
+
+               disable_irq(mhi_cntrl->irq[mhi_event->irq]);
        }
 
        return 0;
@@ -425,74 +446,65 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
        struct device *dev = &mhi_cntrl->mhi_dev->dev;
        struct {
                u32 offset;
-               u32 mask;
                u32 val;
        } reg_info[] = {
                {
-                       CCABAP_HIGHER, U32_MAX,
+                       CCABAP_HIGHER,
                        upper_32_bits(mhi_cntrl->mhi_ctxt->chan_ctxt_addr),
                },
                {
-                       CCABAP_LOWER, U32_MAX,
+                       CCABAP_LOWER,
                        lower_32_bits(mhi_cntrl->mhi_ctxt->chan_ctxt_addr),
                },
                {
-                       ECABAP_HIGHER, U32_MAX,
+                       ECABAP_HIGHER,
                        upper_32_bits(mhi_cntrl->mhi_ctxt->er_ctxt_addr),
                },
                {
-                       ECABAP_LOWER, U32_MAX,
+                       ECABAP_LOWER,
                        lower_32_bits(mhi_cntrl->mhi_ctxt->er_ctxt_addr),
                },
                {
-                       CRCBAP_HIGHER, U32_MAX,
+                       CRCBAP_HIGHER,
                        upper_32_bits(mhi_cntrl->mhi_ctxt->cmd_ctxt_addr),
                },
                {
-                       CRCBAP_LOWER, U32_MAX,
+                       CRCBAP_LOWER,
                        lower_32_bits(mhi_cntrl->mhi_ctxt->cmd_ctxt_addr),
                },
                {
-                       MHICFG, MHICFG_NER_MASK,
-                       mhi_cntrl->total_ev_rings,
-               },
-               {
-                       MHICFG, MHICFG_NHWER_MASK,
-                       mhi_cntrl->hw_ev_rings,
-               },
-               {
-                       MHICTRLBASE_HIGHER, U32_MAX,
+                       MHICTRLBASE_HIGHER,
                        upper_32_bits(mhi_cntrl->iova_start),
                },
                {
-                       MHICTRLBASE_LOWER, U32_MAX,
+                       MHICTRLBASE_LOWER,
                        lower_32_bits(mhi_cntrl->iova_start),
                },
                {
-                       MHIDATABASE_HIGHER, U32_MAX,
+                       MHIDATABASE_HIGHER,
                        upper_32_bits(mhi_cntrl->iova_start),
                },
                {
-                       MHIDATABASE_LOWER, U32_MAX,
+                       MHIDATABASE_LOWER,
                        lower_32_bits(mhi_cntrl->iova_start),
                },
                {
-                       MHICTRLLIMIT_HIGHER, U32_MAX,
+                       MHICTRLLIMIT_HIGHER,
                        upper_32_bits(mhi_cntrl->iova_stop),
                },
                {
-                       MHICTRLLIMIT_LOWER, U32_MAX,
+                       MHICTRLLIMIT_LOWER,
                        lower_32_bits(mhi_cntrl->iova_stop),
                },
                {
-                       MHIDATALIMIT_HIGHER, U32_MAX,
+                       MHIDATALIMIT_HIGHER,
                        upper_32_bits(mhi_cntrl->iova_stop),
                },
                {
-                       MHIDATALIMIT_LOWER, U32_MAX,
+                       MHIDATALIMIT_LOWER,
                        lower_32_bits(mhi_cntrl->iova_stop),
                },
-               { 0, 0, 0 }
+               {0, 0}
        };
 
        dev_dbg(dev, "Initializing MHI registers\n");
@@ -534,8 +546,22 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
 
        /* Write to MMIO registers */
        for (i = 0; reg_info[i].offset; i++)
-               mhi_write_reg_field(mhi_cntrl, base, reg_info[i].offset,
-                                   reg_info[i].mask, reg_info[i].val);
+               mhi_write_reg(mhi_cntrl, base, reg_info[i].offset,
+                             reg_info[i].val);
+
+       ret = mhi_write_reg_field(mhi_cntrl, base, MHICFG, MHICFG_NER_MASK,
+                                 mhi_cntrl->total_ev_rings);
+       if (ret) {
+               dev_err(dev, "Unable to write MHICFG register\n");
+               return ret;
+       }
+
+       ret = mhi_write_reg_field(mhi_cntrl, base, MHICFG, MHICFG_NHWER_MASK,
+                                 mhi_cntrl->hw_ev_rings);
+       if (ret) {
+               dev_err(dev, "Unable to write MHICFG register\n");
+               return ret;
+       }
 
        return 0;
 }
@@ -960,12 +986,16 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
                goto err_destroy_wq;
        }
 
+       ret = mhi_init_irq_setup(mhi_cntrl);
+       if (ret)
+               goto err_ida_free;
+
        /* Register controller with MHI bus */
        mhi_dev = mhi_alloc_device(mhi_cntrl);
        if (IS_ERR(mhi_dev)) {
                dev_err(mhi_cntrl->cntrl_dev, "Failed to allocate MHI device\n");
                ret = PTR_ERR(mhi_dev);
-               goto err_ida_free;
+               goto error_setup_irq;
        }
 
        mhi_dev->dev_type = MHI_DEVICE_CONTROLLER;
@@ -988,6 +1018,8 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
 
 err_release_dev:
        put_device(&mhi_dev->dev);
+error_setup_irq:
+       mhi_deinit_free_irq(mhi_cntrl);
 err_ida_free:
        ida_free(&mhi_controller_ida, mhi_cntrl->index);
 err_destroy_wq:
@@ -1008,6 +1040,7 @@ void mhi_unregister_controller(struct mhi_controller *mhi_cntrl)
        struct mhi_chan *mhi_chan = mhi_cntrl->mhi_chan;
        unsigned int i;
 
+       mhi_deinit_free_irq(mhi_cntrl);
        mhi_destroy_debugfs(mhi_cntrl);
 
        destroy_workqueue(mhi_cntrl->hiprio_wq);
@@ -1103,8 +1136,15 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl)
                 */
                mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->rddm_image,
                                     mhi_cntrl->rddm_size);
-               if (mhi_cntrl->rddm_image)
-                       mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image);
+               if (mhi_cntrl->rddm_image) {
+                       ret = mhi_rddm_prepare(mhi_cntrl,
+                                              mhi_cntrl->rddm_image);
+                       if (ret) {
+                               mhi_free_bhie_table(mhi_cntrl,
+                                                   mhi_cntrl->rddm_image);
+                               goto error_reg_offset;
+                       }
+               }
        }
 
        mutex_unlock(&mhi_cntrl->pm_mutex);