mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
drm/nouveau/tegra: merge platform setup from nouveau drm
The copyright header in nvkm/engine/device/platform.c has been replaced with the NVIDIA one from drm/nouveau_platform.c, as most of the actual code is now theirs. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
340b0e7c50
commit
43a70661ea
9 changed files with 221 additions and 285 deletions
|
@ -25,10 +25,13 @@
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/agp_backend.h>
|
#include <linux/agp_backend.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
#include <linux/iommu.h>
|
||||||
|
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
#include <soc/tegra/fuse.h>
|
#include <soc/tegra/fuse.h>
|
||||||
|
#include <soc/tegra/pmc.h>
|
||||||
|
|
||||||
#ifndef ioread32_native
|
#ifndef ioread32_native
|
||||||
#ifdef __BIG_ENDIAN
|
#ifdef __BIG_ENDIAN
|
||||||
|
|
|
@ -139,8 +139,6 @@ struct nvkm_device {
|
||||||
struct nvkm_sw *sw;
|
struct nvkm_sw *sw;
|
||||||
struct nvkm_engine *vic;
|
struct nvkm_engine *vic;
|
||||||
struct nvkm_engine *vp;
|
struct nvkm_engine *vp;
|
||||||
|
|
||||||
struct nouveau_platform_gpu *gpu;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nvkm_subdev *nvkm_device_subdev(struct nvkm_device *, int index);
|
struct nvkm_subdev *nvkm_device_subdev(struct nvkm_device *, int index);
|
||||||
|
|
|
@ -1,11 +1,31 @@
|
||||||
#ifndef __NVKM_DEVICE_TEGRA_H__
|
#ifndef __NVKM_DEVICE_TEGRA_H__
|
||||||
#define __NVKM_DEVICE_TEGRA_H__
|
#define __NVKM_DEVICE_TEGRA_H__
|
||||||
#include <core/device.h>
|
#include <core/device.h>
|
||||||
|
#include <core/mm.h>
|
||||||
|
|
||||||
struct nvkm_device_tegra {
|
struct nvkm_device_tegra {
|
||||||
struct nvkm_device device;
|
struct nvkm_device device;
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
|
struct reset_control *rst;
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk *clk_pwr;
|
||||||
|
|
||||||
|
struct regulator *vdd;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
/*
|
||||||
|
* Protects accesses to mm from subsystems
|
||||||
|
*/
|
||||||
|
struct mutex mutex;
|
||||||
|
|
||||||
|
struct nvkm_mm mm;
|
||||||
|
struct iommu_domain *domain;
|
||||||
|
unsigned long pgshift;
|
||||||
|
} iommu;
|
||||||
|
|
||||||
|
int gpu_speedo;
|
||||||
};
|
};
|
||||||
|
|
||||||
int nvkm_device_tegra_new(struct platform_device *,
|
int nvkm_device_tegra_new(struct platform_device *,
|
||||||
|
|
|
@ -19,234 +19,32 @@
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/clk.h>
|
|
||||||
#include <linux/io.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/platform_device.h>
|
|
||||||
#include <linux/of.h>
|
|
||||||
#include <linux/reset.h>
|
|
||||||
#include <linux/regulator/consumer.h>
|
|
||||||
#include <linux/iommu.h>
|
|
||||||
#include <soc/tegra/fuse.h>
|
|
||||||
#include <soc/tegra/pmc.h>
|
|
||||||
|
|
||||||
#include "nouveau_drm.h"
|
|
||||||
#include "nouveau_platform.h"
|
#include "nouveau_platform.h"
|
||||||
|
|
||||||
static int nouveau_platform_power_up(struct nouveau_platform_gpu *gpu)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = regulator_enable(gpu->vdd);
|
|
||||||
if (err)
|
|
||||||
goto err_power;
|
|
||||||
|
|
||||||
err = clk_prepare_enable(gpu->clk);
|
|
||||||
if (err)
|
|
||||||
goto err_clk;
|
|
||||||
err = clk_prepare_enable(gpu->clk_pwr);
|
|
||||||
if (err)
|
|
||||||
goto err_clk_pwr;
|
|
||||||
clk_set_rate(gpu->clk_pwr, 204000000);
|
|
||||||
udelay(10);
|
|
||||||
|
|
||||||
reset_control_assert(gpu->rst);
|
|
||||||
udelay(10);
|
|
||||||
|
|
||||||
err = tegra_powergate_remove_clamping(TEGRA_POWERGATE_3D);
|
|
||||||
if (err)
|
|
||||||
goto err_clamp;
|
|
||||||
udelay(10);
|
|
||||||
|
|
||||||
reset_control_deassert(gpu->rst);
|
|
||||||
udelay(10);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_clamp:
|
|
||||||
clk_disable_unprepare(gpu->clk_pwr);
|
|
||||||
err_clk_pwr:
|
|
||||||
clk_disable_unprepare(gpu->clk);
|
|
||||||
err_clk:
|
|
||||||
regulator_disable(gpu->vdd);
|
|
||||||
err_power:
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
reset_control_assert(gpu->rst);
|
|
||||||
udelay(10);
|
|
||||||
|
|
||||||
clk_disable_unprepare(gpu->clk_pwr);
|
|
||||||
clk_disable_unprepare(gpu->clk);
|
|
||||||
udelay(10);
|
|
||||||
|
|
||||||
err = regulator_disable(gpu->vdd);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_IOMMU_API)
|
|
||||||
|
|
||||||
static void nouveau_platform_probe_iommu(struct device *dev,
|
|
||||||
struct nouveau_platform_gpu *gpu)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
unsigned long pgsize_bitmap;
|
|
||||||
|
|
||||||
mutex_init(&gpu->iommu.mutex);
|
|
||||||
|
|
||||||
if (iommu_present(&platform_bus_type)) {
|
|
||||||
gpu->iommu.domain = iommu_domain_alloc(&platform_bus_type);
|
|
||||||
if (IS_ERR(gpu->iommu.domain))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A IOMMU is only usable if it supports page sizes smaller
|
|
||||||
* or equal to the system's PAGE_SIZE, with a preference if
|
|
||||||
* both are equal.
|
|
||||||
*/
|
|
||||||
pgsize_bitmap = gpu->iommu.domain->ops->pgsize_bitmap;
|
|
||||||
if (pgsize_bitmap & PAGE_SIZE) {
|
|
||||||
gpu->iommu.pgshift = PAGE_SHIFT;
|
|
||||||
} else {
|
|
||||||
gpu->iommu.pgshift = fls(pgsize_bitmap & ~PAGE_MASK);
|
|
||||||
if (gpu->iommu.pgshift == 0) {
|
|
||||||
dev_warn(dev, "unsupported IOMMU page size\n");
|
|
||||||
goto free_domain;
|
|
||||||
}
|
|
||||||
gpu->iommu.pgshift -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = iommu_attach_device(gpu->iommu.domain, dev);
|
|
||||||
if (err)
|
|
||||||
goto free_domain;
|
|
||||||
|
|
||||||
err = nvkm_mm_init(&gpu->iommu._mm, 0,
|
|
||||||
(1ULL << 40) >> gpu->iommu.pgshift, 1);
|
|
||||||
if (err)
|
|
||||||
goto detach_device;
|
|
||||||
|
|
||||||
gpu->iommu.mm = &gpu->iommu._mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
detach_device:
|
|
||||||
iommu_detach_device(gpu->iommu.domain, dev);
|
|
||||||
|
|
||||||
free_domain:
|
|
||||||
iommu_domain_free(gpu->iommu.domain);
|
|
||||||
|
|
||||||
error:
|
|
||||||
gpu->iommu.domain = NULL;
|
|
||||||
gpu->iommu.pgshift = 0;
|
|
||||||
dev_err(dev, "cannot initialize IOMMU MM\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nouveau_platform_remove_iommu(struct device *dev,
|
|
||||||
struct nouveau_platform_gpu *gpu)
|
|
||||||
{
|
|
||||||
if (gpu->iommu.domain) {
|
|
||||||
nvkm_mm_fini(&gpu->iommu._mm);
|
|
||||||
iommu_detach_device(gpu->iommu.domain, dev);
|
|
||||||
iommu_domain_free(gpu->iommu.domain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static void nouveau_platform_probe_iommu(struct device *dev,
|
|
||||||
struct nouveau_platform_gpu *gpu)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nouveau_platform_remove_iommu(struct device *dev,
|
|
||||||
struct nouveau_platform_gpu *gpu)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int nouveau_platform_probe(struct platform_device *pdev)
|
static int nouveau_platform_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct nouveau_platform_gpu *gpu;
|
|
||||||
struct nvkm_device *device;
|
struct nvkm_device *device;
|
||||||
struct drm_device *drm;
|
struct drm_device *drm;
|
||||||
int err;
|
int ret;
|
||||||
|
|
||||||
gpu = devm_kzalloc(&pdev->dev, sizeof(*gpu), GFP_KERNEL);
|
|
||||||
if (!gpu)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
gpu->vdd = devm_regulator_get(&pdev->dev, "vdd");
|
|
||||||
if (IS_ERR(gpu->vdd))
|
|
||||||
return PTR_ERR(gpu->vdd);
|
|
||||||
|
|
||||||
gpu->rst = devm_reset_control_get(&pdev->dev, "gpu");
|
|
||||||
if (IS_ERR(gpu->rst))
|
|
||||||
return PTR_ERR(gpu->rst);
|
|
||||||
|
|
||||||
gpu->clk = devm_clk_get(&pdev->dev, "gpu");
|
|
||||||
if (IS_ERR(gpu->clk))
|
|
||||||
return PTR_ERR(gpu->clk);
|
|
||||||
|
|
||||||
gpu->clk_pwr = devm_clk_get(&pdev->dev, "pwr");
|
|
||||||
if (IS_ERR(gpu->clk_pwr))
|
|
||||||
return PTR_ERR(gpu->clk_pwr);
|
|
||||||
|
|
||||||
nouveau_platform_probe_iommu(&pdev->dev, gpu);
|
|
||||||
|
|
||||||
err = nouveau_platform_power_up(gpu);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
drm = nouveau_platform_device_create(pdev, &device);
|
drm = nouveau_platform_device_create(pdev, &device);
|
||||||
if (IS_ERR(drm)) {
|
if (IS_ERR(drm))
|
||||||
err = PTR_ERR(drm);
|
return PTR_ERR(drm);
|
||||||
goto power_down;
|
|
||||||
|
ret = drm_dev_register(drm, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
drm_dev_unref(drm);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
device->gpu = gpu;
|
|
||||||
gpu->gpu_speedo = tegra_sku_info.gpu_speedo_value;
|
|
||||||
|
|
||||||
err = drm_dev_register(drm, 0);
|
|
||||||
if (err < 0)
|
|
||||||
goto err_unref;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_unref:
|
|
||||||
drm_dev_unref(drm);
|
|
||||||
|
|
||||||
power_down:
|
|
||||||
nouveau_platform_power_down(gpu);
|
|
||||||
nouveau_platform_remove_iommu(&pdev->dev, gpu);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nouveau_platform_remove(struct platform_device *pdev)
|
static int nouveau_platform_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct drm_device *drm_dev = platform_get_drvdata(pdev);
|
struct drm_device *dev = platform_get_drvdata(pdev);
|
||||||
struct nouveau_drm *drm = nouveau_drm(drm_dev);
|
nouveau_drm_device_remove(dev);
|
||||||
struct nvkm_device *device = nvxx_device(&drm->device);
|
return 0;
|
||||||
struct nouveau_platform_gpu *gpu = device->gpu;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
nouveau_drm_device_remove(drm_dev);
|
|
||||||
|
|
||||||
err = nouveau_platform_power_down(gpu);
|
|
||||||
|
|
||||||
nouveau_platform_remove_iommu(&pdev->dev, gpu);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_OF)
|
#if IS_ENABLED(CONFIG_OF)
|
||||||
|
|
|
@ -19,44 +19,9 @@
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __NOUVEAU_PLATFORM_H__
|
#ifndef __NOUVEAU_PLATFORM_H__
|
||||||
#define __NOUVEAU_PLATFORM_H__
|
#define __NOUVEAU_PLATFORM_H__
|
||||||
|
#include "nouveau_drm.h"
|
||||||
#include "core/device.h"
|
|
||||||
#include "core/mm.h"
|
|
||||||
|
|
||||||
struct reset_control;
|
|
||||||
struct clk;
|
|
||||||
struct regulator;
|
|
||||||
struct iommu_domain;
|
|
||||||
struct platform_driver;
|
|
||||||
|
|
||||||
struct nouveau_platform_gpu {
|
|
||||||
struct reset_control *rst;
|
|
||||||
struct clk *clk;
|
|
||||||
struct clk *clk_pwr;
|
|
||||||
|
|
||||||
struct regulator *vdd;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
/*
|
|
||||||
* Protects accesses to mm from subsystems
|
|
||||||
*/
|
|
||||||
struct mutex mutex;
|
|
||||||
|
|
||||||
struct nvkm_mm _mm;
|
|
||||||
/*
|
|
||||||
* Just points to _mm. We need this to avoid embedding
|
|
||||||
* struct nvkm_mm in os.h
|
|
||||||
*/
|
|
||||||
struct nvkm_mm *mm;
|
|
||||||
struct iommu_domain *domain;
|
|
||||||
unsigned long pgshift;
|
|
||||||
} iommu;
|
|
||||||
|
|
||||||
int gpu_speedo;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct platform_driver nouveau_platform_driver;
|
extern struct platform_driver nouveau_platform_driver;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2015 Red Hat Inc.
|
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -14,17 +14,138 @@
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*
|
|
||||||
* Authors: Ben Skeggs <bskeggs@redhat.com>
|
|
||||||
*/
|
*/
|
||||||
#include <core/tegra.h>
|
#include <core/tegra.h>
|
||||||
#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER
|
#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER
|
||||||
#include "priv.h"
|
#include "priv.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = regulator_enable(tdev->vdd);
|
||||||
|
if (ret)
|
||||||
|
goto err_power;
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(tdev->clk);
|
||||||
|
if (ret)
|
||||||
|
goto err_clk;
|
||||||
|
ret = clk_prepare_enable(tdev->clk_pwr);
|
||||||
|
if (ret)
|
||||||
|
goto err_clk_pwr;
|
||||||
|
clk_set_rate(tdev->clk_pwr, 204000000);
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
|
reset_control_assert(tdev->rst);
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
|
ret = tegra_powergate_remove_clamping(TEGRA_POWERGATE_3D);
|
||||||
|
if (ret)
|
||||||
|
goto err_clamp;
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
|
reset_control_deassert(tdev->rst);
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_clamp:
|
||||||
|
clk_disable_unprepare(tdev->clk_pwr);
|
||||||
|
err_clk_pwr:
|
||||||
|
clk_disable_unprepare(tdev->clk);
|
||||||
|
err_clk:
|
||||||
|
regulator_disable(tdev->vdd);
|
||||||
|
err_power:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nvkm_device_tegra_power_down(struct nvkm_device_tegra *tdev)
|
||||||
|
{
|
||||||
|
reset_control_assert(tdev->rst);
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
|
clk_disable_unprepare(tdev->clk_pwr);
|
||||||
|
clk_disable_unprepare(tdev->clk);
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
|
return regulator_disable(tdev->vdd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
|
||||||
|
{
|
||||||
|
#if IS_ENABLED(CONFIG_IOMMU_API)
|
||||||
|
struct device *dev = &tdev->pdev->dev;
|
||||||
|
unsigned long pgsize_bitmap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_init(&tdev->iommu.mutex);
|
||||||
|
|
||||||
|
if (iommu_present(&platform_bus_type)) {
|
||||||
|
tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type);
|
||||||
|
if (IS_ERR(tdev->iommu.domain))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A IOMMU is only usable if it supports page sizes smaller
|
||||||
|
* or equal to the system's PAGE_SIZE, with a preference if
|
||||||
|
* both are equal.
|
||||||
|
*/
|
||||||
|
pgsize_bitmap = tdev->iommu.domain->ops->pgsize_bitmap;
|
||||||
|
if (pgsize_bitmap & PAGE_SIZE) {
|
||||||
|
tdev->iommu.pgshift = PAGE_SHIFT;
|
||||||
|
} else {
|
||||||
|
tdev->iommu.pgshift = fls(pgsize_bitmap & ~PAGE_MASK);
|
||||||
|
if (tdev->iommu.pgshift == 0) {
|
||||||
|
dev_warn(dev, "unsupported IOMMU page size\n");
|
||||||
|
goto free_domain;
|
||||||
|
}
|
||||||
|
tdev->iommu.pgshift -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = iommu_attach_device(tdev->iommu.domain, dev);
|
||||||
|
if (ret)
|
||||||
|
goto free_domain;
|
||||||
|
|
||||||
|
ret = nvkm_mm_init(&tdev->iommu.mm, 0,
|
||||||
|
(1ULL << 40) >> tdev->iommu.pgshift, 1);
|
||||||
|
if (ret)
|
||||||
|
goto detach_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
detach_device:
|
||||||
|
iommu_detach_device(tdev->iommu.domain, dev);
|
||||||
|
|
||||||
|
free_domain:
|
||||||
|
iommu_domain_free(tdev->iommu.domain);
|
||||||
|
|
||||||
|
error:
|
||||||
|
tdev->iommu.domain = NULL;
|
||||||
|
tdev->iommu.pgshift = 0;
|
||||||
|
dev_err(dev, "cannot initialize IOMMU MM\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nvkm_device_tegra_remove_iommu(struct nvkm_device_tegra *tdev)
|
||||||
|
{
|
||||||
|
#if IS_ENABLED(CONFIG_IOMMU_API)
|
||||||
|
if (tdev->iommu.domain) {
|
||||||
|
nvkm_mm_fini(&tdev->iommu.mm);
|
||||||
|
iommu_detach_device(tdev->iommu.domain, tdev->device.dev);
|
||||||
|
iommu_domain_free(tdev->iommu.domain);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static struct nvkm_device_tegra *
|
static struct nvkm_device_tegra *
|
||||||
nvkm_device_tegra(struct nvkm_device *device)
|
nvkm_device_tegra(struct nvkm_device *device)
|
||||||
{
|
{
|
||||||
|
@ -95,9 +216,19 @@ nvkm_device_tegra_init(struct nvkm_device *device)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
nvkm_device_tegra_dtor(struct nvkm_device *device)
|
||||||
|
{
|
||||||
|
struct nvkm_device_tegra *tdev = nvkm_device_tegra(device);
|
||||||
|
nvkm_device_tegra_power_down(tdev);
|
||||||
|
nvkm_device_tegra_remove_iommu(tdev);
|
||||||
|
return tdev;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct nvkm_device_func
|
static const struct nvkm_device_func
|
||||||
nvkm_device_tegra_func = {
|
nvkm_device_tegra_func = {
|
||||||
.tegra = nvkm_device_tegra,
|
.tegra = nvkm_device_tegra,
|
||||||
|
.dtor = nvkm_device_tegra_dtor,
|
||||||
.init = nvkm_device_tegra_init,
|
.init = nvkm_device_tegra_init,
|
||||||
.fini = nvkm_device_tegra_fini,
|
.fini = nvkm_device_tegra_fini,
|
||||||
.resource_addr = nvkm_device_tegra_resource_addr,
|
.resource_addr = nvkm_device_tegra_resource_addr,
|
||||||
|
@ -112,6 +243,7 @@ nvkm_device_tegra_new(struct platform_device *pdev,
|
||||||
struct nvkm_device **pdevice)
|
struct nvkm_device **pdevice)
|
||||||
{
|
{
|
||||||
struct nvkm_device_tegra *tdev;
|
struct nvkm_device_tegra *tdev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL)))
|
if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -119,10 +251,37 @@ nvkm_device_tegra_new(struct platform_device *pdev,
|
||||||
tdev->pdev = pdev;
|
tdev->pdev = pdev;
|
||||||
tdev->irq = -1;
|
tdev->irq = -1;
|
||||||
|
|
||||||
return nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev,
|
tdev->vdd = devm_regulator_get(&pdev->dev, "vdd");
|
||||||
NVKM_DEVICE_TEGRA, pdev->id, NULL,
|
if (IS_ERR(tdev->vdd))
|
||||||
cfg, dbg, detect, mmio, subdev_mask,
|
return PTR_ERR(tdev->vdd);
|
||||||
&tdev->device);
|
|
||||||
|
tdev->rst = devm_reset_control_get(&pdev->dev, "gpu");
|
||||||
|
if (IS_ERR(tdev->rst))
|
||||||
|
return PTR_ERR(tdev->rst);
|
||||||
|
|
||||||
|
tdev->clk = devm_clk_get(&pdev->dev, "gpu");
|
||||||
|
if (IS_ERR(tdev->clk))
|
||||||
|
return PTR_ERR(tdev->clk);
|
||||||
|
|
||||||
|
tdev->clk_pwr = devm_clk_get(&pdev->dev, "pwr");
|
||||||
|
if (IS_ERR(tdev->clk_pwr))
|
||||||
|
return PTR_ERR(tdev->clk_pwr);
|
||||||
|
|
||||||
|
nvkm_device_tegra_probe_iommu(tdev);
|
||||||
|
|
||||||
|
ret = nvkm_device_tegra_power_up(tdev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
tdev->gpu_speedo = tegra_sku_info.gpu_speedo_value;
|
||||||
|
ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev,
|
||||||
|
NVKM_DEVICE_TEGRA, pdev->id, NULL,
|
||||||
|
cfg, dbg, detect, mmio, subdev_mask,
|
||||||
|
&tdev->device);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int
|
int
|
||||||
|
|
|
@ -25,12 +25,9 @@
|
||||||
#define gk20a_clk(p) container_of((p), struct gk20a_clk, base)
|
#define gk20a_clk(p) container_of((p), struct gk20a_clk, base)
|
||||||
#include "priv.h"
|
#include "priv.h"
|
||||||
|
|
||||||
|
#include <core/tegra.h>
|
||||||
#include <subdev/timer.h>
|
#include <subdev/timer.h>
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
#include <nouveau_platform.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MHZ (1000 * 1000)
|
#define MHZ (1000 * 1000)
|
||||||
|
|
||||||
#define MASK(w) ((1 << w) - 1)
|
#define MASK(w) ((1 << w) - 1)
|
||||||
|
@ -649,6 +646,7 @@ gk20a_clk = {
|
||||||
int
|
int
|
||||||
gk20a_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk)
|
gk20a_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk)
|
||||||
{
|
{
|
||||||
|
struct nvkm_device_tegra *tdev = device->func->tegra(device);
|
||||||
struct gk20a_clk *clk;
|
struct gk20a_clk *clk;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
|
@ -663,7 +661,7 @@ gk20a_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk)
|
||||||
}
|
}
|
||||||
|
|
||||||
clk->params = &gk20a_pllg_params;
|
clk->params = &gk20a_pllg_params;
|
||||||
clk->parent_rate = clk_get_rate(device->gpu->clk);
|
clk->parent_rate = clk_get_rate(tdev->clk);
|
||||||
|
|
||||||
ret = nvkm_clk_ctor(&gk20a_clk, device, index, true, &clk->base);
|
ret = nvkm_clk_ctor(&gk20a_clk, device, index, true, &clk->base);
|
||||||
nvkm_info(&clk->base.subdev, "parent clock rate: %d Mhz\n",
|
nvkm_info(&clk->base.subdev, "parent clock rate: %d Mhz\n",
|
||||||
|
|
|
@ -42,14 +42,9 @@
|
||||||
|
|
||||||
#include <core/memory.h>
|
#include <core/memory.h>
|
||||||
#include <core/mm.h>
|
#include <core/mm.h>
|
||||||
|
#include <core/tegra.h>
|
||||||
#include <subdev/fb.h>
|
#include <subdev/fb.h>
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
#include <linux/dma-attrs.h>
|
|
||||||
#include <linux/iommu.h>
|
|
||||||
#include <nouveau_platform.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define gk20a_instobj(p) container_of((p), struct gk20a_instobj, memory)
|
#define gk20a_instobj(p) container_of((p), struct gk20a_instobj, memory)
|
||||||
|
|
||||||
struct gk20a_instobj {
|
struct gk20a_instobj {
|
||||||
|
@ -423,8 +418,9 @@ gk20a_instmem = {
|
||||||
|
|
||||||
int
|
int
|
||||||
gk20a_instmem_new(struct nvkm_device *device, int index,
|
gk20a_instmem_new(struct nvkm_device *device, int index,
|
||||||
struct nvkm_instmem **pimem)
|
struct nvkm_instmem **pimem)
|
||||||
{
|
{
|
||||||
|
struct nvkm_device_tegra *tdev = device->func->tegra(device);
|
||||||
struct gk20a_instmem *imem;
|
struct gk20a_instmem *imem;
|
||||||
|
|
||||||
if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL)))
|
if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL)))
|
||||||
|
@ -433,11 +429,11 @@ gk20a_instmem_new(struct nvkm_device *device, int index,
|
||||||
spin_lock_init(&imem->lock);
|
spin_lock_init(&imem->lock);
|
||||||
*pimem = &imem->base;
|
*pimem = &imem->base;
|
||||||
|
|
||||||
if (device->gpu->iommu.domain) {
|
if (tdev->iommu.domain) {
|
||||||
imem->domain = device->gpu->iommu.domain;
|
imem->domain = tdev->iommu.domain;
|
||||||
imem->mm = device->gpu->iommu.mm;
|
imem->mm = &tdev->iommu.mm;
|
||||||
imem->iommu_pgshift = device->gpu->iommu.pgshift;
|
imem->iommu_pgshift = tdev->iommu.pgshift;
|
||||||
imem->mm_mutex = &device->gpu->iommu.mutex;
|
imem->mm_mutex = &tdev->iommu.mutex;
|
||||||
|
|
||||||
nvkm_info(&imem->base.subdev, "using IOMMU\n");
|
nvkm_info(&imem->base.subdev, "using IOMMU\n");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -22,9 +22,7 @@
|
||||||
#define gk20a_volt(p) container_of((p), struct gk20a_volt, base)
|
#define gk20a_volt(p) container_of((p), struct gk20a_volt, base)
|
||||||
#include "priv.h"
|
#include "priv.h"
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#include <core/tegra.h>
|
||||||
#include <nouveau_platform.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct cvb_coef {
|
struct cvb_coef {
|
||||||
int c0;
|
int c0;
|
||||||
|
@ -159,6 +157,7 @@ gk20a_volt = {
|
||||||
int
|
int
|
||||||
gk20a_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt)
|
gk20a_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt)
|
||||||
{
|
{
|
||||||
|
struct nvkm_device_tegra *tdev = device->func->tegra(device);
|
||||||
struct gk20a_volt *volt;
|
struct gk20a_volt *volt;
|
||||||
int i, uv;
|
int i, uv;
|
||||||
|
|
||||||
|
@ -168,10 +167,10 @@ gk20a_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt)
|
||||||
nvkm_volt_ctor(&gk20a_volt, device, index, &volt->base);
|
nvkm_volt_ctor(&gk20a_volt, device, index, &volt->base);
|
||||||
*pvolt = &volt->base;
|
*pvolt = &volt->base;
|
||||||
|
|
||||||
uv = regulator_get_voltage(device->gpu->vdd);
|
uv = regulator_get_voltage(tdev->vdd);
|
||||||
nvkm_info(&volt->base.subdev, "The default voltage is %duV\n", uv);
|
nvkm_info(&volt->base.subdev, "The default voltage is %duV\n", uv);
|
||||||
|
|
||||||
volt->vdd = device->gpu->vdd;
|
volt->vdd = tdev->vdd;
|
||||||
|
|
||||||
volt->base.vid_nr = ARRAY_SIZE(gk20a_cvb_coef);
|
volt->base.vid_nr = ARRAY_SIZE(gk20a_cvb_coef);
|
||||||
nvkm_debug(&volt->base.subdev, "%s - vid_nr = %d\n", __func__,
|
nvkm_debug(&volt->base.subdev, "%s - vid_nr = %d\n", __func__,
|
||||||
|
@ -180,7 +179,7 @@ gk20a_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt)
|
||||||
volt->base.vid[i].vid = i;
|
volt->base.vid[i].vid = i;
|
||||||
volt->base.vid[i].uv =
|
volt->base.vid[i].uv =
|
||||||
gk20a_volt_calc_voltage(&gk20a_cvb_coef[i],
|
gk20a_volt_calc_voltage(&gk20a_cvb_coef[i],
|
||||||
device->gpu->gpu_speedo);
|
tdev->gpu_speedo);
|
||||||
nvkm_debug(&volt->base.subdev, "%2d: vid=%d, uv=%d\n", i,
|
nvkm_debug(&volt->base.subdev, "%2d: vid=%d, uv=%d\n", i,
|
||||||
volt->base.vid[i].vid, volt->base.vid[i].uv);
|
volt->base.vid[i].vid, volt->base.vid[i].uv);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue