u32 freq;
};
+/*
+ * Proved that G2D does not leak protected conents that it is processing.
+ */
+#define G2D_DEVICE_CAPS_SELF_PROTECTION 1
+
struct g2d_device {
unsigned long state;
+ unsigned long caps;
struct miscdevice misc[2];
struct device *dev;
static void g2d_set_start_commands(struct g2d_task *task)
{
+ bool self_prot = task->g2d_dev->caps & G2D_DEVICE_CAPS_SELF_PROTECTION;
struct g2d_reg *regs = page_address(task->cmd_page);
unsigned int n;
- if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
+ if (!self_prot && IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
return;
/*
return 0;
}
+struct g2d_device_data {
+ unsigned long caps;
+};
+
+const struct g2d_device_data g2d_9820_data __initconst = {
+ .caps = G2D_DEVICE_CAPS_SELF_PROTECTION,
+};
+
+static const struct of_device_id of_g2d_match[] __refconst = {
+ {
+ .compatible = "samsung,exynos9810-g2d",
+ }, {
+ .compatible = "samsung,exynos9820-g2d",
+ .data = &g2d_9820_data,
+ },
+ {},
+};
+
static int g2d_probe(struct platform_device *pdev)
{
+ const struct of_device_id *of_id;
struct g2d_device *g2d_dev;
struct resource *res;
__u32 version;
if (ret < 0)
return ret;
+ of_id = of_match_node(of_g2d_match, pdev->dev.of_node);
+ if (of_id->data) {
+ const struct g2d_device_data *devdata = of_id->data;
+
+ g2d_dev->caps = devdata->caps;
+ }
+
ret = iovmm_activate(&pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to activate iommu\n");
SET_RUNTIME_PM_OPS(NULL, g2d_runtime_resume, g2d_runtime_suspend)
};
-static const struct of_device_id of_g2d_match[] = {
- {
- .compatible = "samsung,exynos9810-g2d",
- },
- {},
-};
-
static struct platform_driver g2d_driver = {
.probe = g2d_probe,
.remove = g2d_remove,
void g2d_hw_push_task(struct g2d_device *g2d_dev, struct g2d_task *task)
{
- u32 state;
+ bool self_prot = g2d_dev->caps & G2D_DEVICE_CAPS_SELF_PROTECTION;
+ u32 state = g2d_hw_get_job_state(g2d_dev, task->job_id);
- if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION)) {
- g2d_hw_push_task_by_smc(g2d_dev, task);
- return;
- }
-
- state = g2d_hw_get_job_state(g2d_dev, task->job_id);
if (state != G2D_JOB_STATE_DONE)
dev_err(g2d_dev->dev, "%s: Unexpected state %#x of JOB %d\n",
__func__, state, task->job_id);
+ if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION)) {
+ unsigned int i;
+
+ if (!self_prot) {
+ g2d_hw_push_task_by_smc(g2d_dev, task);
+ return;
+ }
+
+ state = 0;
+
+ for (i = 0; i < task->num_source; i++)
+ if (task->source[i].flags & G2D_LAYERFLAG_SECURE)
+ state |= 1 << i;
+
+ if ((task->target.flags & G2D_LAYERFLAG_SECURE) || state)
+ state |= 1 << 24;
+
+ writel_relaxed(state,
+ g2d_dev->reg +
+ G2D_JOBn_LAYER_SECURE_REG(task->job_id));
+ }
+
writel_relaxed(G2D_JOB_HEADER_DATA(task->priority, task->job_id),
g2d_dev->reg + G2D_JOB_HEADER_REG);
#define G2D_BITBLT_COMMAND_REG 0x104
#define G2D_LAYER_UPDATE_REG 0x108
+/* G2D Secure mode registers */
+#define G2D_JOBn_LAYER_SECURE_REG(n) (0x9004 + (n) * 8)
+
/* HWFC related Registers */
#define G2D_HWFC_CAPTURE_IDX_REG 0x8000
#define G2D_HWFC_ENCODING_IDX_REG 0x8004
#include "g2d_debug.h"
#include "g2d_secure.h"
-static void g2d_secure_enable(void)
+static void g2d_secure_enable(bool self_prot)
{
- if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
+ if (!self_prot && IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
exynos_smc(SMC_PROTECTION_SET, 0, G2D_ALWAYS_S, 1);
}
-static void g2d_secure_disable(void)
+static void g2d_secure_disable(bool self_prot)
{
- if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
+ if (!self_prot && IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
exynos_smc(SMC_PROTECTION_SET, 0, G2D_ALWAYS_S, 0);
}
static int g2d_map_cmd_data(struct g2d_task *task)
{
+ bool self_prot = task->g2d_dev->caps & G2D_DEVICE_CAPS_SELF_PROTECTION;
struct scatterlist sgl;
- if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
+ if (!self_prot && IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
return 0;
/* mapping the command data */
g2d_stamp_task(task, G2D_STAMP_STATE_DONE,
(int)ktime_us_delta(task->ktime_end, task->ktime_begin));
- g2d_secure_disable();
+ g2d_secure_disable(g2d_dev->caps & G2D_DEVICE_CAPS_SELF_PROTECTION);
clk_disable(g2d_dev->clock);
static void g2d_execute_task(struct g2d_device *g2d_dev, struct g2d_task *task)
{
- g2d_secure_enable();
+ g2d_secure_enable(g2d_dev->caps & G2D_DEVICE_CAPS_SELF_PROTECTION);
list_move_tail(&task->node, &g2d_dev->tasks_active);
change_task_state_active(task);