Commit 62c1e124 authored by Oded Gabbay's avatar Oded Gabbay
Browse files

habanalabs: add opcode to INFO IOCTL to return clock rate



Add a new opcode to the INFO IOCTL to allow the user application to
retrieve the ASIC's current and maximum clock rate. The rate is
returned in MHz.

Signed-off-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
Reviewed-by: default avatarTomer Tayar <ttayar@habana.ai>
parent 8fdacf2a
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -5148,7 +5148,8 @@ static const struct hl_asic_funcs goya_funcs = {
	.init_iatu = goya_init_iatu,
	.rreg = hl_rreg,
	.wreg = hl_wreg,
	.halt_coresight = goya_halt_coresight
	.halt_coresight = goya_halt_coresight,
	.get_clk_rate = goya_get_clk_rate
};

/*
+2 −0
Original line number Diff line number Diff line
@@ -233,4 +233,6 @@ void goya_cpu_accessible_dma_pool_free(struct hl_device *hdev, size_t size,
					void *vaddr);
void goya_mmu_remove_device_cpu_mappings(struct hl_device *hdev);

int goya_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk);

#endif /* GOYAP_H_ */
+31 −0
Original line number Diff line number Diff line
@@ -32,6 +32,37 @@ void goya_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq)
	}
}

int goya_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk)
{
	long value;

	if (hl_device_disabled_or_in_reset(hdev))
		return -ENODEV;

	value = hl_get_frequency(hdev, MME_PLL, false);

	if (value < 0) {
		dev_err(hdev->dev, "Failed to retrieve device max clock %ld\n",
			value);
		return value;
	}

	*max_clk = (value / 1000 / 1000);

	value = hl_get_frequency(hdev, MME_PLL, true);

	if (value < 0) {
		dev_err(hdev->dev,
			"Failed to retrieve device current clock %ld\n",
			value);
		return value;
	}

	*cur_clk = (value / 1000 / 1000);

	return 0;
}

static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr,
				char *buf)
{
+2 −0
Original line number Diff line number Diff line
@@ -508,6 +508,7 @@ enum hl_pll_frequency {
 * @rreg: Read a register. Needed for simulator support.
 * @wreg: Write a register. Needed for simulator support.
 * @halt_coresight: stop the ETF and ETR traces.
 * @get_clk_rate: Retrieve the ASIC current and maximum clock rate in MHz
 */
struct hl_asic_funcs {
	int (*early_init)(struct hl_device *hdev);
@@ -590,6 +591,7 @@ struct hl_asic_funcs {
	u32 (*rreg)(struct hl_device *hdev, u32 reg);
	void (*wreg)(struct hl_device *hdev, u32 reg, u32 val);
	void (*halt_coresight)(struct hl_device *hdev);
	int (*get_clk_rate)(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk);
};


+23 −0
Original line number Diff line number Diff line
@@ -221,6 +221,25 @@ static int device_utilization(struct hl_device *hdev, struct hl_info_args *args)
		min((size_t) max_size, sizeof(device_util))) ? -EFAULT : 0;
}

static int get_clk_rate(struct hl_device *hdev, struct hl_info_args *args)
{
	struct hl_info_clk_rate clk_rate = {0};
	u32 max_size = args->return_size;
	void __user *out = (void __user *) (uintptr_t) args->return_pointer;
	int rc;

	if ((!max_size) || (!out))
		return -EINVAL;

	rc = hdev->asic_funcs->get_clk_rate(hdev, &clk_rate.cur_clk_rate_mhz,
						&clk_rate.max_clk_rate_mhz);
	if (rc)
		return rc;

	return copy_to_user(out, &clk_rate,
		min((size_t) max_size, sizeof(clk_rate))) ? -EFAULT : 0;
}

static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data,
				struct device *dev)
{
@@ -271,6 +290,10 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data,
		rc = hw_events_info(hdev, true, args);
		break;

	case HL_INFO_CLK_RATE:
		rc = get_clk_rate(hdev, args);
		break;

	default:
		dev_err(dev, "Invalid request %d\n", args->op);
		rc = -ENOTTY;
Loading