diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-06 14:18:59 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-06 14:18:59 -0800 |
commit | 45763bf4bc1ebdf8eb95697607e1fd042a3e1221 (patch) | |
tree | c5b26c2d5d1190247b59d6d1fe68b8a247351362 /drivers/misc/habanalabs/goya/goya_hwmgr.c | |
parent | da2577fe63f865cd9dc785a42c29c0071f567a35 (diff) | |
parent | 142a0f83b216a607aebed42e54a1be620765e28c (diff) | |
download | linux-stable-45763bf4bc1ebdf8eb95697607e1fd042a3e1221.tar.gz linux-stable-45763bf4bc1ebdf8eb95697607e1fd042a3e1221.tar.bz2 linux-stable-45763bf4bc1ebdf8eb95697607e1fd042a3e1221.zip |
Merge tag 'char-misc-5.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH:
"Here is the big char/misc driver patch pull request for 5.1-rc1.
The largest thing by far is the new habanalabs driver for their AI
accelerator chip. For now it is in the drivers/misc directory but will
probably move to a new directory soon along with other drivers of this
type.
Other than that, just the usual set of individual driver updates and
fixes. There's an "odd" merge in here from the DRM tree that they
asked me to do as the MEI driver is starting to interact with the i915
driver, and it needed some coordination. All of those patches have
been properly acked by the relevant subsystem maintainers.
All of these have been in linux-next with no reported issues, most for
quite some time"
* tag 'char-misc-5.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (219 commits)
habanalabs: adjust Kconfig to fix build errors
habanalabs: use %px instead of %p in error print
habanalabs: use do_div for 64-bit divisions
intel_th: gth: Fix an off-by-one in output unassigning
habanalabs: fix little-endian<->cpu conversion warnings
habanalabs: use NULL to initialize array of pointers
habanalabs: fix little-endian<->cpu conversion warnings
habanalabs: soft-reset device if context-switch fails
habanalabs: print pointer using %p
habanalabs: fix memory leak with CBs with unaligned size
habanalabs: return correct error code on MMU mapping failure
habanalabs: add comments in uapi/misc/habanalabs.h
habanalabs: extend QMAN0 job timeout
habanalabs: set DMA0 completion to SOB 1007
habanalabs: fix validation of WREG32 to DMA completion
habanalabs: fix mmu cache registers init
habanalabs: disable CPU access on timeouts
habanalabs: add MMU DRAM default page mapping
habanalabs: Dissociate RAZWI info from event types
misc/habanalabs: adjust Kconfig to fix build errors
...
Diffstat (limited to 'drivers/misc/habanalabs/goya/goya_hwmgr.c')
-rw-r--r-- | drivers/misc/habanalabs/goya/goya_hwmgr.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/drivers/misc/habanalabs/goya/goya_hwmgr.c b/drivers/misc/habanalabs/goya/goya_hwmgr.c new file mode 100644 index 000000000000..088692c852b6 --- /dev/null +++ b/drivers/misc/habanalabs/goya/goya_hwmgr.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright 2016-2019 HabanaLabs, Ltd. + * All Rights Reserved. + */ + +#include "goyaP.h" + +void goya_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq) +{ + struct goya_device *goya = hdev->asic_specific; + + switch (freq) { + case PLL_HIGH: + hl_set_frequency(hdev, MME_PLL, hdev->high_pll); + hl_set_frequency(hdev, TPC_PLL, hdev->high_pll); + hl_set_frequency(hdev, IC_PLL, hdev->high_pll); + break; + case PLL_LOW: + hl_set_frequency(hdev, MME_PLL, GOYA_PLL_FREQ_LOW); + hl_set_frequency(hdev, TPC_PLL, GOYA_PLL_FREQ_LOW); + hl_set_frequency(hdev, IC_PLL, GOYA_PLL_FREQ_LOW); + break; + case PLL_LAST: + hl_set_frequency(hdev, MME_PLL, goya->mme_clk); + hl_set_frequency(hdev, TPC_PLL, goya->tpc_clk); + hl_set_frequency(hdev, IC_PLL, goya->ic_clk); + break; + default: + dev_err(hdev->dev, "unknown frequency setting\n"); + } +} + +static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct hl_device *hdev = dev_get_drvdata(dev); + long value; + + if (hl_device_disabled_or_in_reset(hdev)) + return -ENODEV; + + value = hl_get_frequency(hdev, MME_PLL, false); + + if (value < 0) + return value; + + return sprintf(buf, "%lu\n", value); +} + +static ssize_t mme_clk_store(struct device *dev, 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; + int rc; + long value; + + if (hl_device_disabled_or_in_reset(hdev)) { + count = -ENODEV; + goto fail; + } + + if (hdev->pm_mng_profile == PM_AUTO) { + count = -EPERM; + goto fail; + } + + rc = kstrtoul(buf, 0, &value); + + if (rc) { + count = -EINVAL; + goto fail; + } + + hl_set_frequency(hdev, MME_PLL, value); + goya->mme_clk = value; + +fail: + return count; +} + +static ssize_t tpc_clk_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct hl_device *hdev = dev_get_drvdata(dev); + long value; + + if (hl_device_disabled_or_in_reset(hdev)) + return -ENODEV; + + value = hl_get_frequency(hdev, TPC_PLL, false); + + if (value < 0) + return value; + + return sprintf(buf, "%lu\n", value); +} + +static ssize_t tpc_clk_store(struct device *dev, 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; + int rc; + long value; + + if (hl_device_disabled_or_in_reset(hdev)) { + count = -ENODEV; + goto fail; + } + + if (hdev->pm_mng_profile == PM_AUTO) { + count = -EPERM; + goto fail; + } + + rc = kstrtoul(buf, 0, &value); + + if (rc) { + count = -EINVAL; + goto fail; + } + + hl_set_frequency(hdev, TPC_PLL, value); + goya->tpc_clk = value; + +fail: + return count; +} + +static ssize_t ic_clk_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct hl_device *hdev = dev_get_drvdata(dev); + long value; + + if (hl_device_disabled_or_in_reset(hdev)) + return -ENODEV; + + value = hl_get_frequency(hdev, IC_PLL, false); + + if (value < 0) + return value; + + return sprintf(buf, "%lu\n", value); +} + +static ssize_t ic_clk_store(struct device *dev, 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; + int rc; + long value; + + if (hl_device_disabled_or_in_reset(hdev)) { + count = -ENODEV; + goto fail; + } + + if (hdev->pm_mng_profile == PM_AUTO) { + count = -EPERM; + goto fail; + } + + rc = kstrtoul(buf, 0, &value); + + if (rc) { + count = -EINVAL; + goto fail; + } + + hl_set_frequency(hdev, IC_PLL, value); + goya->ic_clk = value; + +fail: + return count; +} + +static ssize_t mme_clk_curr_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hl_device *hdev = dev_get_drvdata(dev); + long value; + + if (hl_device_disabled_or_in_reset(hdev)) + return -ENODEV; + + value = hl_get_frequency(hdev, MME_PLL, true); + + if (value < 0) + return value; + + return sprintf(buf, "%lu\n", value); +} + +static ssize_t tpc_clk_curr_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hl_device *hdev = dev_get_drvdata(dev); + long value; + + if (hl_device_disabled_or_in_reset(hdev)) + return -ENODEV; + + value = hl_get_frequency(hdev, TPC_PLL, true); + + if (value < 0) + return value; + + return sprintf(buf, "%lu\n", value); +} + +static ssize_t ic_clk_curr_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hl_device *hdev = dev_get_drvdata(dev); + long value; + + if (hl_device_disabled_or_in_reset(hdev)) + return -ENODEV; + + value = hl_get_frequency(hdev, IC_PLL, true); + + if (value < 0) + return value; + + return sprintf(buf, "%lu\n", value); +} + +static DEVICE_ATTR_RW(ic_clk); +static DEVICE_ATTR_RO(ic_clk_curr); +static DEVICE_ATTR_RW(mme_clk); +static DEVICE_ATTR_RO(mme_clk_curr); +static DEVICE_ATTR_RW(tpc_clk); +static DEVICE_ATTR_RO(tpc_clk_curr); + +static struct attribute *goya_dev_attrs[] = { + &dev_attr_ic_clk.attr, + &dev_attr_ic_clk_curr.attr, + &dev_attr_mme_clk.attr, + &dev_attr_mme_clk_curr.attr, + &dev_attr_tpc_clk.attr, + &dev_attr_tpc_clk_curr.attr, + NULL, +}; + +void goya_add_device_attr(struct hl_device *hdev, + struct attribute_group *dev_attr_grp) +{ + dev_attr_grp->attrs = goya_dev_attrs; +} |