0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/errno.h>
0009 #include <linux/sched.h>
0010 #include <linux/kernel.h>
0011 #include <linux/mm.h>
0012 #include <linux/poll.h>
0013 #include <linux/smp.h>
0014 #include <linux/stddef.h>
0015 #include <linux/unistd.h>
0016
0017 #include <asm/io.h>
0018 #include <asm/spu.h>
0019 #include <asm/spu_priv1.h>
0020 #include <asm/spu_csa.h>
0021 #include <asm/mmu_context.h>
0022 #include "spufs.h"
0023
0024 static int spu_hw_mbox_read(struct spu_context *ctx, u32 * data)
0025 {
0026 struct spu *spu = ctx->spu;
0027 struct spu_problem __iomem *prob = spu->problem;
0028 u32 mbox_stat;
0029 int ret = 0;
0030
0031 spin_lock_irq(&spu->register_lock);
0032 mbox_stat = in_be32(&prob->mb_stat_R);
0033 if (mbox_stat & 0x0000ff) {
0034 *data = in_be32(&prob->pu_mb_R);
0035 ret = 4;
0036 }
0037 spin_unlock_irq(&spu->register_lock);
0038 return ret;
0039 }
0040
0041 static u32 spu_hw_mbox_stat_read(struct spu_context *ctx)
0042 {
0043 return in_be32(&ctx->spu->problem->mb_stat_R);
0044 }
0045
0046 static __poll_t spu_hw_mbox_stat_poll(struct spu_context *ctx, __poll_t events)
0047 {
0048 struct spu *spu = ctx->spu;
0049 __poll_t ret = 0;
0050 u32 stat;
0051
0052 spin_lock_irq(&spu->register_lock);
0053 stat = in_be32(&spu->problem->mb_stat_R);
0054
0055
0056
0057
0058
0059
0060 if (events & (EPOLLIN | EPOLLRDNORM)) {
0061 if (stat & 0xff0000)
0062 ret |= EPOLLIN | EPOLLRDNORM;
0063 else {
0064 spu_int_stat_clear(spu, 2, CLASS2_MAILBOX_INTR);
0065 spu_int_mask_or(spu, 2, CLASS2_ENABLE_MAILBOX_INTR);
0066 }
0067 }
0068 if (events & (EPOLLOUT | EPOLLWRNORM)) {
0069 if (stat & 0x00ff00)
0070 ret = EPOLLOUT | EPOLLWRNORM;
0071 else {
0072 spu_int_stat_clear(spu, 2,
0073 CLASS2_MAILBOX_THRESHOLD_INTR);
0074 spu_int_mask_or(spu, 2,
0075 CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR);
0076 }
0077 }
0078 spin_unlock_irq(&spu->register_lock);
0079 return ret;
0080 }
0081
0082 static int spu_hw_ibox_read(struct spu_context *ctx, u32 * data)
0083 {
0084 struct spu *spu = ctx->spu;
0085 struct spu_problem __iomem *prob = spu->problem;
0086 struct spu_priv2 __iomem *priv2 = spu->priv2;
0087 int ret;
0088
0089 spin_lock_irq(&spu->register_lock);
0090 if (in_be32(&prob->mb_stat_R) & 0xff0000) {
0091
0092 *data = in_be64(&priv2->puint_mb_R);
0093 ret = 4;
0094 } else {
0095
0096 spu_int_mask_or(spu, 2, CLASS2_ENABLE_MAILBOX_INTR);
0097 ret = 0;
0098 }
0099 spin_unlock_irq(&spu->register_lock);
0100 return ret;
0101 }
0102
0103 static int spu_hw_wbox_write(struct spu_context *ctx, u32 data)
0104 {
0105 struct spu *spu = ctx->spu;
0106 struct spu_problem __iomem *prob = spu->problem;
0107 int ret;
0108
0109 spin_lock_irq(&spu->register_lock);
0110 if (in_be32(&prob->mb_stat_R) & 0x00ff00) {
0111
0112 out_be32(&prob->spu_mb_W, data);
0113 ret = 4;
0114 } else {
0115
0116
0117 spu_int_mask_or(spu, 2, CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR);
0118 ret = 0;
0119 }
0120 spin_unlock_irq(&spu->register_lock);
0121 return ret;
0122 }
0123
0124 static void spu_hw_signal1_write(struct spu_context *ctx, u32 data)
0125 {
0126 out_be32(&ctx->spu->problem->signal_notify1, data);
0127 }
0128
0129 static void spu_hw_signal2_write(struct spu_context *ctx, u32 data)
0130 {
0131 out_be32(&ctx->spu->problem->signal_notify2, data);
0132 }
0133
0134 static void spu_hw_signal1_type_set(struct spu_context *ctx, u64 val)
0135 {
0136 struct spu *spu = ctx->spu;
0137 struct spu_priv2 __iomem *priv2 = spu->priv2;
0138 u64 tmp;
0139
0140 spin_lock_irq(&spu->register_lock);
0141 tmp = in_be64(&priv2->spu_cfg_RW);
0142 if (val)
0143 tmp |= 1;
0144 else
0145 tmp &= ~1;
0146 out_be64(&priv2->spu_cfg_RW, tmp);
0147 spin_unlock_irq(&spu->register_lock);
0148 }
0149
0150 static u64 spu_hw_signal1_type_get(struct spu_context *ctx)
0151 {
0152 return ((in_be64(&ctx->spu->priv2->spu_cfg_RW) & 1) != 0);
0153 }
0154
0155 static void spu_hw_signal2_type_set(struct spu_context *ctx, u64 val)
0156 {
0157 struct spu *spu = ctx->spu;
0158 struct spu_priv2 __iomem *priv2 = spu->priv2;
0159 u64 tmp;
0160
0161 spin_lock_irq(&spu->register_lock);
0162 tmp = in_be64(&priv2->spu_cfg_RW);
0163 if (val)
0164 tmp |= 2;
0165 else
0166 tmp &= ~2;
0167 out_be64(&priv2->spu_cfg_RW, tmp);
0168 spin_unlock_irq(&spu->register_lock);
0169 }
0170
0171 static u64 spu_hw_signal2_type_get(struct spu_context *ctx)
0172 {
0173 return ((in_be64(&ctx->spu->priv2->spu_cfg_RW) & 2) != 0);
0174 }
0175
0176 static u32 spu_hw_npc_read(struct spu_context *ctx)
0177 {
0178 return in_be32(&ctx->spu->problem->spu_npc_RW);
0179 }
0180
0181 static void spu_hw_npc_write(struct spu_context *ctx, u32 val)
0182 {
0183 out_be32(&ctx->spu->problem->spu_npc_RW, val);
0184 }
0185
0186 static u32 spu_hw_status_read(struct spu_context *ctx)
0187 {
0188 return in_be32(&ctx->spu->problem->spu_status_R);
0189 }
0190
0191 static char *spu_hw_get_ls(struct spu_context *ctx)
0192 {
0193 return ctx->spu->local_store;
0194 }
0195
0196 static void spu_hw_privcntl_write(struct spu_context *ctx, u64 val)
0197 {
0198 out_be64(&ctx->spu->priv2->spu_privcntl_RW, val);
0199 }
0200
0201 static u32 spu_hw_runcntl_read(struct spu_context *ctx)
0202 {
0203 return in_be32(&ctx->spu->problem->spu_runcntl_RW);
0204 }
0205
0206 static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val)
0207 {
0208 spin_lock_irq(&ctx->spu->register_lock);
0209 if (val & SPU_RUNCNTL_ISOLATE)
0210 spu_hw_privcntl_write(ctx,
0211 SPU_PRIVCNT_LOAD_REQUEST_ENABLE_MASK);
0212 out_be32(&ctx->spu->problem->spu_runcntl_RW, val);
0213 spin_unlock_irq(&ctx->spu->register_lock);
0214 }
0215
0216 static void spu_hw_runcntl_stop(struct spu_context *ctx)
0217 {
0218 spin_lock_irq(&ctx->spu->register_lock);
0219 out_be32(&ctx->spu->problem->spu_runcntl_RW, SPU_RUNCNTL_STOP);
0220 while (in_be32(&ctx->spu->problem->spu_status_R) & SPU_STATUS_RUNNING)
0221 cpu_relax();
0222 spin_unlock_irq(&ctx->spu->register_lock);
0223 }
0224
0225 static void spu_hw_master_start(struct spu_context *ctx)
0226 {
0227 struct spu *spu = ctx->spu;
0228 u64 sr1;
0229
0230 spin_lock_irq(&spu->register_lock);
0231 sr1 = spu_mfc_sr1_get(spu) | MFC_STATE1_MASTER_RUN_CONTROL_MASK;
0232 spu_mfc_sr1_set(spu, sr1);
0233 spin_unlock_irq(&spu->register_lock);
0234 }
0235
0236 static void spu_hw_master_stop(struct spu_context *ctx)
0237 {
0238 struct spu *spu = ctx->spu;
0239 u64 sr1;
0240
0241 spin_lock_irq(&spu->register_lock);
0242 sr1 = spu_mfc_sr1_get(spu) & ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
0243 spu_mfc_sr1_set(spu, sr1);
0244 spin_unlock_irq(&spu->register_lock);
0245 }
0246
0247 static int spu_hw_set_mfc_query(struct spu_context * ctx, u32 mask, u32 mode)
0248 {
0249 struct spu_problem __iomem *prob = ctx->spu->problem;
0250 int ret;
0251
0252 spin_lock_irq(&ctx->spu->register_lock);
0253 ret = -EAGAIN;
0254 if (in_be32(&prob->dma_querytype_RW))
0255 goto out;
0256 ret = 0;
0257 out_be32(&prob->dma_querymask_RW, mask);
0258 out_be32(&prob->dma_querytype_RW, mode);
0259 out:
0260 spin_unlock_irq(&ctx->spu->register_lock);
0261 return ret;
0262 }
0263
0264 static u32 spu_hw_read_mfc_tagstatus(struct spu_context * ctx)
0265 {
0266 return in_be32(&ctx->spu->problem->dma_tagstatus_R);
0267 }
0268
0269 static u32 spu_hw_get_mfc_free_elements(struct spu_context *ctx)
0270 {
0271 return in_be32(&ctx->spu->problem->dma_qstatus_R);
0272 }
0273
0274 static int spu_hw_send_mfc_command(struct spu_context *ctx,
0275 struct mfc_dma_command *cmd)
0276 {
0277 u32 status;
0278 struct spu_problem __iomem *prob = ctx->spu->problem;
0279
0280 spin_lock_irq(&ctx->spu->register_lock);
0281 out_be32(&prob->mfc_lsa_W, cmd->lsa);
0282 out_be64(&prob->mfc_ea_W, cmd->ea);
0283 out_be32(&prob->mfc_union_W.by32.mfc_size_tag32,
0284 cmd->size << 16 | cmd->tag);
0285 out_be32(&prob->mfc_union_W.by32.mfc_class_cmd32,
0286 cmd->class << 16 | cmd->cmd);
0287 status = in_be32(&prob->mfc_union_W.by32.mfc_class_cmd32);
0288 spin_unlock_irq(&ctx->spu->register_lock);
0289
0290 switch (status & 0xffff) {
0291 case 0:
0292 return 0;
0293 case 2:
0294 return -EAGAIN;
0295 default:
0296 return -EINVAL;
0297 }
0298 }
0299
0300 static void spu_hw_restart_dma(struct spu_context *ctx)
0301 {
0302 struct spu_priv2 __iomem *priv2 = ctx->spu->priv2;
0303
0304 if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &ctx->spu->flags))
0305 out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND);
0306 }
0307
0308 struct spu_context_ops spu_hw_ops = {
0309 .mbox_read = spu_hw_mbox_read,
0310 .mbox_stat_read = spu_hw_mbox_stat_read,
0311 .mbox_stat_poll = spu_hw_mbox_stat_poll,
0312 .ibox_read = spu_hw_ibox_read,
0313 .wbox_write = spu_hw_wbox_write,
0314 .signal1_write = spu_hw_signal1_write,
0315 .signal2_write = spu_hw_signal2_write,
0316 .signal1_type_set = spu_hw_signal1_type_set,
0317 .signal1_type_get = spu_hw_signal1_type_get,
0318 .signal2_type_set = spu_hw_signal2_type_set,
0319 .signal2_type_get = spu_hw_signal2_type_get,
0320 .npc_read = spu_hw_npc_read,
0321 .npc_write = spu_hw_npc_write,
0322 .status_read = spu_hw_status_read,
0323 .get_ls = spu_hw_get_ls,
0324 .privcntl_write = spu_hw_privcntl_write,
0325 .runcntl_read = spu_hw_runcntl_read,
0326 .runcntl_write = spu_hw_runcntl_write,
0327 .runcntl_stop = spu_hw_runcntl_stop,
0328 .master_start = spu_hw_master_start,
0329 .master_stop = spu_hw_master_stop,
0330 .set_mfc_query = spu_hw_set_mfc_query,
0331 .read_mfc_tagstatus = spu_hw_read_mfc_tagstatus,
0332 .get_mfc_free_elements = spu_hw_get_mfc_free_elements,
0333 .send_mfc_command = spu_hw_send_mfc_command,
0334 .restart_dma = spu_hw_restart_dma,
0335 };