Skip to content

Commit

Permalink
drm/nouveau/tegra: merge platform setup from nouveau drm
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ben Skeggs committed Aug 28, 2015
1 parent 340b0e7 commit 43a7066
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 285 deletions.
3 changes: 3 additions & 0 deletions drivers/gpu/drm/nouveau/include/nvif/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/agp_backend.h>
#include <linux/reset.h>
#include <linux/iommu.h>

#include <asm/unaligned.h>

#include <soc/tegra/fuse.h>
#include <soc/tegra/pmc.h>

#ifndef ioread32_native
#ifdef __BIG_ENDIAN
Expand Down
2 changes: 0 additions & 2 deletions drivers/gpu/drm/nouveau/include/nvkm/core/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ struct nvkm_device {
struct nvkm_sw *sw;
struct nvkm_engine *vic;
struct nvkm_engine *vp;

struct nouveau_platform_gpu *gpu;
};

struct nvkm_subdev *nvkm_device_subdev(struct nvkm_device *, int index);
Expand Down
20 changes: 20 additions & 0 deletions drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
#ifndef __NVKM_DEVICE_TEGRA_H__
#define __NVKM_DEVICE_TEGRA_H__
#include <core/device.h>
#include <core/mm.h>

struct nvkm_device_tegra {
struct nvkm_device device;
struct platform_device *pdev;
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 *,
Expand Down
224 changes: 11 additions & 213 deletions drivers/gpu/drm/nouveau/nouveau_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,234 +19,32 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* 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"

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)
{
struct nouveau_platform_gpu *gpu;
struct nvkm_device *device;
struct drm_device *drm;
int err;

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;
int ret;

drm = nouveau_platform_device_create(pdev, &device);
if (IS_ERR(drm)) {
err = PTR_ERR(drm);
goto power_down;
}
if (IS_ERR(drm))
return PTR_ERR(drm);

device->gpu = gpu;
gpu->gpu_speedo = tegra_sku_info.gpu_speedo_value;

err = drm_dev_register(drm, 0);
if (err < 0)
goto err_unref;
ret = drm_dev_register(drm, 0);
if (ret < 0) {
drm_dev_unref(drm);
return ret;
}

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)
{
struct drm_device *drm_dev = platform_get_drvdata(pdev);
struct nouveau_drm *drm = nouveau_drm(drm_dev);
struct nvkm_device *device = nvxx_device(&drm->device);
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;
struct drm_device *dev = platform_get_drvdata(pdev);
nouveau_drm_device_remove(dev);
return 0;
}

#if IS_ENABLED(CONFIG_OF)
Expand Down
37 changes: 1 addition & 36 deletions drivers/gpu/drm/nouveau/nouveau_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,44 +19,9 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

#ifndef __NOUVEAU_PLATFORM_H__
#define __NOUVEAU_PLATFORM_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;
};
#include "nouveau_drm.h"

extern struct platform_driver nouveau_platform_driver;
#endif
Loading

0 comments on commit 43a7066

Please sign in to comment.