aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2017-02-14 01:56:10 -0500
committerBen Skeggs <bskeggs@redhat.com>2017-03-07 02:05:13 -0500
commit6ac2cc209e0096dabc8e902a8620d45f41b9fc0b (patch)
tree1ad51b3563042d5a6cb4130e3b6e7ec058b00c2c
parentcfd044b02873b02236bcd93ff398504d489ddc13 (diff)
drm/nouveau/falcon: support for EMEM
On SEC, DMEM is unaccessible by the CPU when the falcon is running in LS mode. This makes communication with the firmware using DMEM impossible. For this purpose, a new kind of memory (EMEM) has been added. It works similarly to DMEM, with the difference that its address space starts at 0x1000000. For this reason, it makes sense to treat it like a special case of DMEM. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/base.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/v1.c63
3 files changed, 65 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
index b04d3a0e82e6..9f84ef24a8b3 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
@@ -25,6 +25,7 @@ struct nvkm_falcon {
25 u8 version; 25 u8 version;
26 u8 secret; 26 u8 secret;
27 bool debug; 27 bool debug;
28 bool has_emem;
28 29
29 struct nvkm_memory *core; 30 struct nvkm_memory *core;
30 bool external; 31 bool external;
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c
index a4c6ee6ffde6..1b7f48efd8b1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c
@@ -202,6 +202,7 @@ nvkm_falcon_ctor(const struct nvkm_falcon_func *func,
202 break; 202 break;
203 case NVKM_ENGINE_SEC2: 203 case NVKM_ENGINE_SEC2:
204 debug_reg = 0x408; 204 debug_reg = 0x408;
205 falcon->has_emem = true;
205 break; 206 break;
206 default: 207 default:
207 nvkm_warn(subdev, "unsupported falcon %s!\n", 208 nvkm_warn(subdev, "unsupported falcon %s!\n",
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c
index 2a3c8bfb084a..669c24028470 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c
@@ -65,12 +65,44 @@ nvkm_falcon_v1_load_imem(struct nvkm_falcon *falcon, void *data, u32 start,
65} 65}
66 66
67static void 67static void
68nvkm_falcon_v1_load_emem(struct nvkm_falcon *falcon, void *data, u32 start,
69 u32 size, u8 port)
70{
71 u8 rem = size % 4;
72 int i;
73
74 size -= rem;
75
76 nvkm_falcon_wr32(falcon, 0xac0 + (port * 8), start | (0x1 << 24));
77 for (i = 0; i < size / 4; i++)
78 nvkm_falcon_wr32(falcon, 0xac4 + (port * 8), ((u32 *)data)[i]);
79
80 /*
81 * If size is not a multiple of 4, mask the last word to ensure garbage
82 * does not get written
83 */
84 if (rem) {
85 u32 extra = ((u32 *)data)[i];
86
87 nvkm_falcon_wr32(falcon, 0xac4 + (port * 8),
88 extra & (BIT(rem * 8) - 1));
89 }
90}
91
92static const u32 EMEM_START_ADDR = 0x1000000;
93
94static void
68nvkm_falcon_v1_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start, 95nvkm_falcon_v1_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start,
69 u32 size, u8 port) 96 u32 size, u8 port)
70{ 97{
71 u8 rem = size % 4; 98 u8 rem = size % 4;
72 int i; 99 int i;
73 100
101 if (start >= EMEM_START_ADDR && falcon->has_emem)
102 return nvkm_falcon_v1_load_emem(falcon, data,
103 start - EMEM_START_ADDR, size,
104 port);
105
74 size -= rem; 106 size -= rem;
75 107
76 nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), start | (0x1 << 24)); 108 nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), start | (0x1 << 24));
@@ -90,12 +122,43 @@ nvkm_falcon_v1_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start,
90} 122}
91 123
92static void 124static void
125nvkm_falcon_v1_read_emem(struct nvkm_falcon *falcon, u32 start, u32 size,
126 u8 port, void *data)
127{
128 u8 rem = size % 4;
129 int i;
130
131 size -= rem;
132
133 nvkm_falcon_wr32(falcon, 0xac0 + (port * 8), start | (0x1 << 25));
134 for (i = 0; i < size / 4; i++)
135 ((u32 *)data)[i] = nvkm_falcon_rd32(falcon, 0xac4 + (port * 8));
136
137 /*
138 * If size is not a multiple of 4, mask the last word to ensure garbage
139 * does not get read
140 */
141 if (rem) {
142 u32 extra = nvkm_falcon_rd32(falcon, 0xac4 + (port * 8));
143
144 for (i = size; i < size + rem; i++) {
145 ((u8 *)data)[i] = (u8)(extra & 0xff);
146 extra >>= 8;
147 }
148 }
149}
150
151static void
93nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, 152nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size,
94 u8 port, void *data) 153 u8 port, void *data)
95{ 154{
96 u8 rem = size % 4; 155 u8 rem = size % 4;
97 int i; 156 int i;
98 157
158 if (start >= EMEM_START_ADDR && falcon->has_emem)
159 return nvkm_falcon_v1_read_emem(falcon, start - EMEM_START_ADDR,
160 size, port, data);
161
99 size -= rem; 162 size -= rem;
100 163
101 nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), start | (0x1 << 25)); 164 nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), start | (0x1 << 25));