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 struct spu_context_ops spu_hw_ops
= {
190 .mbox_read
= spu_hw_mbox_read
,
191 .mbox_stat_read
= spu_hw_mbox_stat_read
,
192 .ibox_read
= spu_hw_ibox_read
,
193 .wbox_write
= spu_hw_wbox_write
,
194 .signal1_read
= spu_hw_signal1_read
,
195 .signal1_write
= spu_hw_signal1_write
,
196 .signal2_read
= spu_hw_signal2_read
,
197 .signal2_write
= spu_hw_signal2_write
,
198 .signal1_type_set
= spu_hw_signal1_type_set
,
199 .signal1_type_get
= spu_hw_signal1_type_get
,
200 .signal2_type_set
= spu_hw_signal2_type_set
,
201 .signal2_type_get
= spu_hw_signal2_type_get
,
202 .npc_read
= spu_hw_npc_read
,
203 .npc_write
= spu_hw_npc_write
,
204 .status_read
= spu_hw_status_read
,
205 .get_ls
= spu_hw_get_ls
,