1 /* hw_ops.c - query/set operations on active SPU context.
3 * Copyright (C) IBM 2005
4 * Author: Mark Nutter <mnutter@us.ibm.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <linux/config.h>
22 #include <linux/module.h>
23 #include <linux/errno.h>
24 #include <linux/sched.h>
25 #include <linux/kernel.h>
27 #include <linux/vmalloc.h>
28 #include <linux/smp.h>
29 #include <linux/smp_lock.h>
30 #include <linux/stddef.h>
31 #include <linux/unistd.h>
35 #include <asm/spu_csa.h>
36 #include <asm/mmu_context.h>
39 static int spu_hw_mbox_read(struct spu_context *ctx, u32 * data)
41 struct spu *spu = ctx->spu;
42 struct spu_problem __iomem *prob = spu->problem;
46 spin_lock_irq(&spu->register_lock);
47 mbox_stat = in_be32(&prob->mb_stat_R);
48 if (mbox_stat & 0x0000ff) {
49 *data = in_be32(&prob->pu_mb_R);
52 spin_unlock_irq(&spu->register_lock);
56 static u32 spu_hw_mbox_stat_read(struct spu_context *ctx)
58 return in_be32(&ctx->spu->problem->mb_stat_R);
61 static int spu_hw_ibox_read(struct spu_context *ctx, u32 * data)
63 struct spu *spu = ctx->spu;
64 struct spu_problem __iomem *prob = spu->problem;
65 struct spu_priv1 __iomem *priv1 = spu->priv1;
66 struct spu_priv2 __iomem *priv2 = spu->priv2;
69 spin_lock_irq(&spu->register_lock);
70 if (in_be32(&prob->mb_stat_R) & 0xff0000) {
71 /* read the first available word */
72 *data = in_be64(&priv2->puint_mb_R);
75 /* make sure we get woken up by the interrupt */
76 out_be64(&priv1->int_mask_class2_RW,
77 in_be64(&priv1->int_mask_class2_RW) | 0x1);
80 spin_unlock_irq(&spu->register_lock);
84 static int spu_hw_wbox_write(struct spu_context *ctx, u32 data)
86 struct spu *spu = ctx->spu;
87 struct spu_problem __iomem *prob = spu->problem;
88 struct spu_priv1 __iomem *priv1 = spu->priv1;
91 spin_lock_irq(&spu->register_lock);
92 if (in_be32(&prob->mb_stat_R) & 0x00ff00) {
93 /* we have space to write wbox_data to */
94 out_be32(&prob->spu_mb_W, data);
97 /* make sure we get woken up by the interrupt when space
99 out_be64(&priv1->int_mask_class2_RW,
100 in_be64(&priv1->int_mask_class2_RW) | 0x10);
103 spin_unlock_irq(&spu->register_lock);
107 static u32 spu_hw_signal1_read(struct spu_context *ctx)
109 return in_be32(&ctx->spu->problem->signal_notify1);
112 static void spu_hw_signal1_write(struct spu_context *ctx, u32 data)
114 out_be32(&ctx->spu->problem->signal_notify1, data);
117 static u32 spu_hw_signal2_read(struct spu_context *ctx)
119 return in_be32(&ctx->spu->problem->signal_notify1);
122 static void spu_hw_signal2_write(struct spu_context *ctx, u32 data)
124 out_be32(&ctx->spu->problem->signal_notify2, data);
127 static void spu_hw_signal1_type_set(struct spu_context *ctx, u64 val)
129 struct spu *spu = ctx->spu;
130 struct spu_priv2 __iomem *priv2 = spu->priv2;
133 spin_lock_irq(&spu->register_lock);
134 tmp = in_be64(&priv2->spu_cfg_RW);
139 out_be64(&priv2->spu_cfg_RW, tmp);
140 spin_unlock_irq(&spu->register_lock);
143 static u64 spu_hw_signal1_type_get(struct spu_context *ctx)
145 return ((in_be64(&ctx->spu->priv2->spu_cfg_RW) & 1) != 0);
148 static void spu_hw_signal2_type_set(struct spu_context *ctx, u64 val)
150 struct spu *spu = ctx->spu;
151 struct spu_priv2 __iomem *priv2 = spu->priv2;
154 spin_lock_irq(&spu->register_lock);
155 tmp = in_be64(&priv2->spu_cfg_RW);
160 out_be64(&priv2->spu_cfg_RW, tmp);
161 spin_unlock_irq(&spu->register_lock);
164 static u64 spu_hw_signal2_type_get(struct spu_context *ctx)
166 return ((in_be64(&ctx->spu->priv2->spu_cfg_RW) & 2) != 0);
169 static u32 spu_hw_npc_read(struct spu_context *ctx)
171 return in_be32(&ctx->spu->problem->spu_npc_RW);
174 static void spu_hw_npc_write(struct spu_context *ctx, u32 val)
176 out_be32(&ctx->spu->problem->spu_npc_RW, val);
179 static u32 spu_hw_status_read(struct spu_context *ctx)
181 return in_be32(&ctx->spu->problem->spu_status_R);
184 static char *spu_hw_get_ls(struct spu_context *ctx)
186 return ctx->spu->local_store;
189 static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val)
192 out_be32(&ctx->spu->problem->spu_runcntl_RW, val);
195 static void spu_hw_runcntl_stop(struct spu_context *ctx)
197 spin_lock_irq(&ctx->spu->register_lock);
198 out_be32(&ctx->spu->problem->spu_runcntl_RW, SPU_RUNCNTL_STOP);
199 while (in_be32(&ctx->spu->problem->spu_status_R) & SPU_STATUS_RUNNING)
201 spin_unlock_irq(&ctx->spu->register_lock);
204 struct spu_context_ops spu_hw_ops = {
205 .mbox_read = spu_hw_mbox_read,
206 .mbox_stat_read = spu_hw_mbox_stat_read,
207 .ibox_read = spu_hw_ibox_read,
208 .wbox_write = spu_hw_wbox_write,
209 .signal1_read = spu_hw_signal1_read,
210 .signal1_write = spu_hw_signal1_write,
211 .signal2_read = spu_hw_signal2_read,
212 .signal2_write = spu_hw_signal2_write,
213 .signal1_type_set = spu_hw_signal1_type_set,
214 .signal1_type_get = spu_hw_signal1_type_get,
215 .signal2_type_set = spu_hw_signal2_type_set,
216 .signal2_type_get = spu_hw_signal2_type_get,
217 .npc_read = spu_hw_npc_read,
218 .npc_write = spu_hw_npc_write,
219 .status_read = spu_hw_status_read,
220 .get_ls = spu_hw_get_ls,
221 .runcntl_write = spu_hw_runcntl_write,
222 .runcntl_stop = spu_hw_runcntl_stop,