hdev->asic_funcs->early_fini(hdev);
 }
 
-static void set_freq_to_low_job(struct work_struct *work)
-{
-       struct hl_device *hdev = container_of(work, struct hl_device,
-                                               work_freq.work);
-
-       mutex_lock(&hdev->fpriv_list_lock);
-
-       if (!hdev->compute_ctx)
-               hl_device_set_frequency(hdev, PLL_LOW);
-
-       mutex_unlock(&hdev->fpriv_list_lock);
-
-       schedule_delayed_work(&hdev->work_freq,
-                       usecs_to_jiffies(HL_PLL_LOW_JOB_FREQ_USEC));
-}
-
 static void hl_device_heartbeat(struct work_struct *work)
 {
        struct hl_device *hdev = container_of(work, struct hl_device,
 
        hdev->high_pll = hdev->asic_prop.high_pll;
 
-       /* force setting to low frequency */
-       hdev->curr_pll_profile = PLL_LOW;
-
-       if (hdev->pm_mng_profile == PM_AUTO)
-               hdev->asic_funcs->set_pll_profile(hdev, PLL_LOW);
-       else
-               hdev->asic_funcs->set_pll_profile(hdev, PLL_LAST);
-
-       INIT_DELAYED_WORK(&hdev->work_freq, set_freq_to_low_job);
-       schedule_delayed_work(&hdev->work_freq,
-       usecs_to_jiffies(HL_PLL_LOW_JOB_FREQ_USEC));
-
        if (hdev->heartbeat) {
                INIT_DELAYED_WORK(&hdev->work_heartbeat, hl_device_heartbeat);
                schedule_delayed_work(&hdev->work_heartbeat,
        if (!hdev->late_init_done)
                return;
 
-       cancel_delayed_work_sync(&hdev->work_freq);
        if (hdev->heartbeat)
                cancel_delayed_work_sync(&hdev->work_heartbeat);
 
        return 0;
 }
 
-/*
- * hl_device_set_frequency - set the frequency of the device
- *
- * @hdev: pointer to habanalabs device structure
- * @freq: the new frequency value
- *
- * Change the frequency if needed. This function has no protection against
- * concurrency, therefore it is assumed that the calling function has protected
- * itself against the case of calling this function from multiple threads with
- * different values
- *
- * Returns 0 if no change was done, otherwise returns 1
- */
-int hl_device_set_frequency(struct hl_device *hdev, enum hl_pll_frequency freq)
-{
-       if ((hdev->pm_mng_profile == PM_MANUAL) ||
-                       (hdev->curr_pll_profile == freq))
-               return 0;
-
-       dev_dbg(hdev->dev, "Changing device frequency to %s\n",
-               freq == PLL_HIGH ? "high" : "low");
-
-       hdev->asic_funcs->set_pll_profile(hdev, freq);
-
-       hdev->curr_pll_profile = freq;
-
-       return 1;
-}
-
 int hl_device_set_debug_mode(struct hl_device *hdev, bool enable)
 {
        int rc = 0;
 
  * @cdev_ctrl: char device for control operations only (INFO IOCTL)
  * @dev: related kernel basic device structure.
  * @dev_ctrl: related kernel device structure for the control device
- * @work_freq: delayed work to lower device frequency if possible.
  * @work_heartbeat: delayed work for CPU-CP is-alive check.
  * @device_reset_work: delayed work which performs hard reset
  * @asic_name: ASIC specific name.
  * @asic_specific: ASIC specific information to use only from ASIC files.
  * @vm: virtual memory manager for MMU.
  * @hwmon_dev: H/W monitor device.
- * @pm_mng_profile: current power management profile.
  * @hl_chip_info: ASIC's sensors information.
  * @device_status_description: device status description.
  * @hl_debugfs: device's debugfs manager.
  * @open_counter: number of successful device open operations.
  * @fw_poll_interval_usec: FW status poll interval in usec.
  * @in_reset: is device in reset flow.
- * @curr_pll_profile: current PLL profile.
  * @card_type: Various ASICs have several card types. This indicates the card
  *             type of the current device.
  * @major: habanalabs kernel driver major.
        struct cdev                     cdev_ctrl;
        struct device                   *dev;
        struct device                   *dev_ctrl;
-       struct delayed_work             work_freq;
        struct delayed_work             work_heartbeat;
        struct hl_device_reset_work     device_reset_work;
        char                            asic_name[HL_STR_MAX];
        void                            *asic_specific;
        struct hl_vm                    vm;
        struct device                   *hwmon_dev;
-       enum hl_pm_mng_profile          pm_mng_profile;
        struct hwmon_chip_info          *hl_chip_info;
 
        struct hl_dbg_device_entry      hl_debugfs;
        u64                             fw_poll_interval_usec;
        atomic_t                        in_reset;
        ktime_t                         last_successful_open_ktime;
-       enum hl_pll_frequency           curr_pll_profile;
        enum cpucp_card_types           card_type;
        u32                             major;
        u32                             high_pll;
 int hl_device_reset(struct hl_device *hdev, u32 flags);
 void hl_hpriv_get(struct hl_fpriv *hpriv);
 int hl_hpriv_put(struct hl_fpriv *hpriv);
-int hl_device_set_frequency(struct hl_device *hdev, enum hl_pll_frequency freq);
 int hl_device_utilization(struct hl_device *hdev, u32 *utilization);
 
 int hl_build_hwmon_channel_info(struct hl_device *hdev,
 
                goto out_err;
        }
 
-       /* Device is IDLE at this point so it is legal to change PLLs.
-        * There is no need to check anything because if the PLL is
-        * already HIGH, the set function will return without doing
-        * anything
-        */
-       hl_device_set_frequency(hdev, PLL_HIGH);
-
        list_add(&hpriv->dev_node, &hdev->fpriv_list);
        mutex_unlock(&hdev->fpriv_list_lock);
 
 
 {
        int rc;
 
-       if (hdev->asic_type == ASIC_GOYA)
-               hdev->pm_mng_profile = PM_AUTO;
-       else
-               hdev->pm_mng_profile = PM_MANUAL;
-
        hdev->max_power = hdev->asic_prop.max_power_default;
 
        hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group);
 
         */
        gaudi_mmu_prepare(hdev, 1);
 
+       hdev->asic_funcs->set_pll_profile(hdev, PLL_LAST);
+
        return 0;
 
 disable_pci_access:
 
        prop->psoc_pci_pll_div_factor = div_fctr;
 }
 
+/*
+ * goya_set_frequency - set the frequency of the device
+ *
+ * @hdev: pointer to habanalabs device structure
+ * @freq: the new frequency value
+ *
+ * Change the frequency if needed. This function has no protection against
+ * concurrency, therefore it is assumed that the calling function has protected
+ * itself against the case of calling this function from multiple threads with
+ * different values
+ *
+ * Returns 0 if no change was done, otherwise returns 1
+ */
+int goya_set_frequency(struct hl_device *hdev, enum hl_pll_frequency freq)
+{
+       struct goya_device *goya = hdev->asic_specific;
+
+       if ((goya->pm_mng_profile == PM_MANUAL) ||
+                       (goya->curr_pll_profile == freq))
+               return 0;
+
+       dev_dbg(hdev->dev, "Changing device frequency to %s\n",
+               freq == PLL_HIGH ? "high" : "low");
+
+       goya_set_pll_profile(hdev, freq);
+
+       goya->curr_pll_profile = freq;
+
+       return 1;
+}
+
+static void goya_set_freq_to_low_job(struct work_struct *work)
+{
+       struct goya_work_freq *goya_work = container_of(work,
+                                               struct goya_work_freq,
+                                               work_freq.work);
+       struct hl_device *hdev = goya_work->hdev;
+
+       mutex_lock(&hdev->fpriv_list_lock);
+
+       if (!hdev->compute_ctx)
+               goya_set_frequency(hdev, PLL_LOW);
+
+       mutex_unlock(&hdev->fpriv_list_lock);
+
+       schedule_delayed_work(&goya_work->work_freq,
+                       usecs_to_jiffies(HL_PLL_LOW_JOB_FREQ_USEC));
+}
+
 int goya_late_init(struct hl_device *hdev)
 {
        struct asic_fixed_properties *prop = &hdev->asic_prop;
+       struct goya_device *goya = hdev->asic_specific;
        int rc;
 
        goya_fetch_psoc_frequency(hdev);
                return rc;
        }
 
+       /* force setting to low frequency */
+       goya->curr_pll_profile = PLL_LOW;
+
+       goya->pm_mng_profile = PM_AUTO;
+
+       hdev->asic_funcs->set_pll_profile(hdev, PLL_LOW);
+
+       schedule_delayed_work(&goya->goya_work->work_freq,
+               usecs_to_jiffies(HL_PLL_LOW_JOB_FREQ_USEC));
+
        return 0;
 }
 
 void goya_late_fini(struct hl_device *hdev)
 {
        const struct hwmon_channel_info **channel_info_arr;
+       struct goya_device *goya = hdev->asic_specific;
        int i = 0;
 
+       cancel_delayed_work_sync(&goya->goya_work->work_freq);
+
        if (!hdev->hl_chip_info->info)
                return;
 
 
        hdev->asic_funcs->set_pci_memory_regions(hdev);
 
+       goya->goya_work = kmalloc(sizeof(struct goya_work_freq), GFP_KERNEL);
+       if (!goya->goya_work) {
+               rc = -ENOMEM;
+               goto free_cpu_accessible_dma_pool;
+       }
+
+       goya->goya_work->hdev = hdev;
+       INIT_DELAYED_WORK(&goya->goya_work->work_freq, goya_set_freq_to_low_job);
+
        return 0;
 
 free_cpu_accessible_dma_pool:
 
        dma_pool_destroy(hdev->dma_pool);
 
+       kfree(goya->goya_work);
        kfree(goya);
 
        return 0;
 
 #define HW_CAP_GOLDEN          0x00000400
 #define HW_CAP_TPC             0x00000800
 
+struct goya_work_freq {
+       struct hl_device *hdev;
+       struct delayed_work work_freq;
+};
+
 struct goya_device {
        /* TODO: remove hw_queues_lock after moving to scheduler code */
        spinlock_t      hw_queues_lock;
+       struct goya_work_freq   *goya_work;
 
        u64             mme_clk;
        u64             tpc_clk;
        u32             events_stat_aggregate[GOYA_ASYNC_EVENT_ID_SIZE];
        u32             hw_cap_initialized;
        u8              device_cpu_mmu_mappings_done;
+
+       enum hl_pll_frequency           curr_pll_profile;
+       enum hl_pm_mng_profile          pm_mng_profile;
 };
 
 int goya_set_fixed_properties(struct hl_device *hdev);
 
 u32 goya_get_queue_id_for_cq(struct hl_device *hdev, u32 cq_idx);
 u64 goya_get_device_time(struct hl_device *hdev);
+int goya_set_frequency(struct hl_device *hdev, enum hl_pll_frequency freq);
 
 #endif /* GOYAP_H_ */
 
                goto fail;
        }
 
-       if (hdev->pm_mng_profile == PM_AUTO) {
+       if (goya->pm_mng_profile == PM_AUTO) {
                count = -EPERM;
                goto fail;
        }
                goto fail;
        }
 
-       if (hdev->pm_mng_profile == PM_AUTO) {
+       if (goya->pm_mng_profile == PM_AUTO) {
                count = -EPERM;
                goto fail;
        }
                goto fail;
        }
 
-       if (hdev->pm_mng_profile == PM_AUTO) {
+       if (goya->pm_mng_profile == PM_AUTO) {
                count = -EPERM;
                goto fail;
        }
                                struct device_attribute *attr, char *buf)
 {
        struct hl_device *hdev = dev_get_drvdata(dev);
+       struct goya_device *goya = hdev->asic_specific;
 
        if (!hl_device_operational(hdev, NULL))
                return -ENODEV;
 
        return sprintf(buf, "%s\n",
-                       (hdev->pm_mng_profile == PM_AUTO) ? "auto" :
-                       (hdev->pm_mng_profile == PM_MANUAL) ? "manual" :
+                       (goya->pm_mng_profile == PM_AUTO) ? "auto" :
+                       (goya->pm_mng_profile == PM_MANUAL) ? "manual" :
                        "unknown");
 }
 
                struct device_attribute *attr, const char *buf, size_t count)
 {
        struct hl_device *hdev = dev_get_drvdata(dev);
+       struct goya_device *goya = hdev->asic_specific;
 
        if (!hl_device_operational(hdev, NULL)) {
                count = -ENODEV;
 
        if (strncmp("auto", buf, strlen("auto")) == 0) {
                /* Make sure we are in LOW PLL when changing modes */
-               if (hdev->pm_mng_profile == PM_MANUAL) {
-                       hdev->curr_pll_profile = PLL_HIGH;
-                       hdev->pm_mng_profile = PM_AUTO;
-                       hl_device_set_frequency(hdev, PLL_LOW);
+               if (goya->pm_mng_profile == PM_MANUAL) {
+                       goya->curr_pll_profile = PLL_HIGH;
+                       goya->pm_mng_profile = PM_AUTO;
+                       goya_set_frequency(hdev, PLL_LOW);
                }
        } else if (strncmp("manual", buf, strlen("manual")) == 0) {
-               if (hdev->pm_mng_profile == PM_AUTO) {
+               if (goya->pm_mng_profile == PM_AUTO) {
                        /* Must release the lock because the work thread also
                         * takes this lock. But before we release it, set
                         * the mode to manual so nothing will change if a user
                         * suddenly opens the device
                         */
-                       hdev->pm_mng_profile = PM_MANUAL;
+                       goya->pm_mng_profile = PM_MANUAL;
 
                        mutex_unlock(&hdev->fpriv_list_lock);
 
                        /* Flush the current work so we can return to the user
                         * knowing that he is the only one changing frequencies
                         */
-                       flush_delayed_work(&hdev->work_freq);
+                       if (goya->goya_work)
+                               flush_delayed_work(&goya->goya_work->work_freq);
 
                        return count;
                }