Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* hw_ops.c - query/set operations on active SPU context.
0003  *
0004  * Copyright (C) IBM 2005
0005  * Author: Mark Nutter <mnutter@us.ibm.com>
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     /* if the requested event is there, return the poll
0056        mask, otherwise enable the interrupt to get notified,
0057        but first mark any pending interrupts as done so
0058        we don't get woken up unnecessarily */
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         /* read the first available word */
0092         *data = in_be64(&priv2->puint_mb_R);
0093         ret = 4;
0094     } else {
0095         /* make sure we get woken up by the interrupt */
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         /* we have space to write wbox_data to */
0112         out_be32(&prob->spu_mb_W, data);
0113         ret = 4;
0114     } else {
0115         /* make sure we get woken up by the interrupt when space
0116            becomes available */
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 };