1de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/* 2de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * PS3 Platform spu routines. 3de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * 4de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * Copyright (C) 2006 Sony Computer Entertainment Inc. 5de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * Copyright 2006 Sony Corp. 6de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * 7de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * This program is free software; you can redistribute it and/or modify 8de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * it under the terms of the GNU General Public License as published by 9de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * the Free Software Foundation; version 2 of the License. 10de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * 11de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * This program is distributed in the hope that it will be useful, 12de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * but WITHOUT ANY WARRANTY; without even the implied warranty of 13de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * GNU General Public License for more details. 15de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * 16de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * You should have received a copy of the GNU General Public License 17de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * along with this program; if not, write to the Free Software 18de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 20de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 21de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <linux/kernel.h> 22de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <linux/init.h> 235a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 24de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <linux/mmzone.h> 2566b15db69c2553036cc25f6e2e74fe7e3aa2761ePaul Gortmaker#include <linux/export.h> 26de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <linux/io.h> 27de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <linux/mm.h> 28de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 29de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <asm/spu.h> 30de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <asm/spu_priv1.h> 31de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <asm/lv1call.h> 3223afcb4e0061c591776a3350db89512d085397c2Takashi Yamamoto#include <asm/ps3.h> 33de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 34c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi#include "../cell/spufs/spufs.h" 352a08ea69a3e448a5cc94e5da9eccc40cf13f9532Geoff Levand#include "platform.h" 362a08ea69a3e448a5cc94e5da9eccc40cf13f9532Geoff Levand 37de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/* spu_management_ops */ 38de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 39de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/** 40de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * enum spe_type - Type of spe to create. 41de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @spe_type_logical: Standard logical spe. 42de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * 43de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * For use with lv1_construct_logical_spe(). The current HV does not support 44de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * any types other than those listed. 45de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 46de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 47de91a53429952875740692d1de36ae70d4cf81daGeoff Levandenum spe_type { 48de91a53429952875740692d1de36ae70d4cf81daGeoff Levand SPE_TYPE_LOGICAL = 0, 49de91a53429952875740692d1de36ae70d4cf81daGeoff Levand}; 50de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 51de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/** 52de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * struct spe_shadow - logical spe shadow register area. 53de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * 54de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * Read-only shadow of spe registers. 55de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 56de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 57de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstruct spe_shadow { 58a8229a9e5211a52839268b82ae14cdf528d48f58Geoff Levand u8 padding_0140[0x0140]; 59de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 int_status_class0_RW; /* 0x0140 */ 60de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 int_status_class1_RW; /* 0x0148 */ 61de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 int_status_class2_RW; /* 0x0150 */ 62de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0158[0x0610-0x0158]; 63de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 mfc_dsisr_RW; /* 0x0610 */ 64de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0618[0x0620-0x0618]; 65de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 mfc_dar_RW; /* 0x0620 */ 66de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0628[0x0800-0x0628]; 67de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 mfc_dsipr_R; /* 0x0800 */ 68de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0808[0x0810-0x0808]; 69de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 mfc_lscrr_R; /* 0x0810 */ 70de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0818[0x0c00-0x0818]; 71de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 mfc_cer_R; /* 0x0c00 */ 72de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0c08[0x0f00-0x0c08]; 73de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 spe_execution_status; /* 0x0f00 */ 74de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0f08[0x1000-0x0f08]; 75a8229a9e5211a52839268b82ae14cdf528d48f58Geoff Levand}; 76de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 77de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/** 78de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * enum spe_ex_state - Logical spe execution state. 79de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @spe_ex_state_unexecutable: Uninitialized. 80de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @spe_ex_state_executable: Enabled, not ready. 81de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @spe_ex_state_executed: Ready for use. 82de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * 83de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * The execution state (status) of the logical spe as reported in 84de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * struct spe_shadow:spe_execution_status. 85de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 86de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 87de91a53429952875740692d1de36ae70d4cf81daGeoff Levandenum spe_ex_state { 88de91a53429952875740692d1de36ae70d4cf81daGeoff Levand SPE_EX_STATE_UNEXECUTABLE = 0, 89de91a53429952875740692d1de36ae70d4cf81daGeoff Levand SPE_EX_STATE_EXECUTABLE = 2, 90de91a53429952875740692d1de36ae70d4cf81daGeoff Levand SPE_EX_STATE_EXECUTED = 3, 91de91a53429952875740692d1de36ae70d4cf81daGeoff Levand}; 92de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 93de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/** 94de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * struct priv1_cache - Cached values of priv1 registers. 95de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @masks[]: Array of cached spe interrupt masks, indexed by class. 96de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @sr1: Cached mfc_sr1 register. 97de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @tclass_id: Cached mfc_tclass_id register. 98de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 99de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 100de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstruct priv1_cache { 101de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 masks[3]; 102de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 sr1; 103de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 tclass_id; 104de91a53429952875740692d1de36ae70d4cf81daGeoff Levand}; 105de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 106de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/** 107de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * struct spu_pdata - Platform state variables. 108de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @spe_id: HV spe id returned by lv1_construct_logical_spe(). 109de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @resource_id: HV spe resource id returned by 110de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * ps3_repository_read_spe_resource_id(). 111de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @priv2_addr: lpar address of spe priv2 area returned by 112de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * lv1_construct_logical_spe(). 113de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @shadow_addr: lpar address of spe register shadow area returned by 114de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * lv1_construct_logical_spe(). 115de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @shadow: Virtual (ioremap) address of spe register shadow area. 116de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @cache: Cached values of priv1 registers. 117de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 118de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 119de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstruct spu_pdata { 120de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 spe_id; 121de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 resource_id; 122de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 priv2_addr; 123de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 shadow_addr; 124de91a53429952875740692d1de36ae70d4cf81daGeoff Levand struct spe_shadow __iomem *shadow; 125de91a53429952875740692d1de36ae70d4cf81daGeoff Levand struct priv1_cache cache; 126de91a53429952875740692d1de36ae70d4cf81daGeoff Levand}; 127de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 128de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic struct spu_pdata *spu_pdata(struct spu *spu) 129de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 130de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return spu->pdata; 131de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 132de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 133de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#define dump_areas(_a, _b, _c, _d, _e) \ 134de91a53429952875740692d1de36ae70d4cf81daGeoff Levand _dump_areas(_a, _b, _c, _d, _e, __func__, __LINE__) 135de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void _dump_areas(unsigned int spe_id, unsigned long priv2, 136de91a53429952875740692d1de36ae70d4cf81daGeoff Levand unsigned long problem, unsigned long ls, unsigned long shadow, 137de91a53429952875740692d1de36ae70d4cf81daGeoff Levand const char* func, int line) 138de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 139de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: spe_id: %xh (%u)\n", func, line, spe_id, spe_id); 140de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: priv2: %lxh\n", func, line, priv2); 141de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: problem: %lxh\n", func, line, problem); 142de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: ls: %lxh\n", func, line, ls); 143de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: shadow: %lxh\n", func, line, shadow); 144de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 145de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 14623afcb4e0061c591776a3350db89512d085397c2Takashi Yamamotoinline u64 ps3_get_spe_id(void *arg) 14723afcb4e0061c591776a3350db89512d085397c2Takashi Yamamoto{ 14823afcb4e0061c591776a3350db89512d085397c2Takashi Yamamoto return spu_pdata(arg)->spe_id; 14923afcb4e0061c591776a3350db89512d085397c2Takashi Yamamoto} 15023afcb4e0061c591776a3350db89512d085397c2Takashi YamamotoEXPORT_SYMBOL_GPL(ps3_get_spe_id); 15123afcb4e0061c591776a3350db89512d085397c2Takashi Yamamoto 152de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic unsigned long get_vas_id(void) 153de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 154b17b3df161814c43c03dbc8dbf8d32741bb30ba4Stephen Rothwell u64 id; 155de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 156de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_get_logical_ppe_id(&id); 157b5ecc5595e4fb2992093b3d2d0e15b4630eb233bGeoff Levand lv1_get_virtual_address_space_id_of_ppe(&id); 158de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 159de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return id; 160de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 161de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 162de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init construct_spu(struct spu *spu) 163de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 164de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 165b17b3df161814c43c03dbc8dbf8d32741bb30ba4Stephen Rothwell u64 unused; 166b17b3df161814c43c03dbc8dbf8d32741bb30ba4Stephen Rothwell u64 problem_phys; 167b17b3df161814c43c03dbc8dbf8d32741bb30ba4Stephen Rothwell u64 local_store_phys; 168de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 169de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = lv1_construct_logical_spe(PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT, 170de91a53429952875740692d1de36ae70d4cf81daGeoff Levand PAGE_SHIFT, PAGE_SHIFT, get_vas_id(), SPE_TYPE_LOGICAL, 171b17b3df161814c43c03dbc8dbf8d32741bb30ba4Stephen Rothwell &spu_pdata(spu)->priv2_addr, &problem_phys, 172b17b3df161814c43c03dbc8dbf8d32741bb30ba4Stephen Rothwell &local_store_phys, &unused, 173de91a53429952875740692d1de36ae70d4cf81daGeoff Levand &spu_pdata(spu)->shadow_addr, 174de91a53429952875740692d1de36ae70d4cf81daGeoff Levand &spu_pdata(spu)->spe_id); 175b17b3df161814c43c03dbc8dbf8d32741bb30ba4Stephen Rothwell spu->problem_phys = problem_phys; 176b17b3df161814c43c03dbc8dbf8d32741bb30ba4Stephen Rothwell spu->local_store_phys = local_store_phys; 177de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 178de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) { 179de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: lv1_construct_logical_spe failed: %s\n", 180de91a53429952875740692d1de36ae70d4cf81daGeoff Levand __func__, __LINE__, ps3_result(result)); 181de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 182de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 183de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 184de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 185de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 186de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 187de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void spu_unmap(struct spu *spu) 188de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 189de91a53429952875740692d1de36ae70d4cf81daGeoff Levand iounmap(spu->priv2); 190de91a53429952875740692d1de36ae70d4cf81daGeoff Levand iounmap(spu->problem); 191de91a53429952875740692d1de36ae70d4cf81daGeoff Levand iounmap((__force u8 __iomem *)spu->local_store); 192de91a53429952875740692d1de36ae70d4cf81daGeoff Levand iounmap(spu_pdata(spu)->shadow); 193de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 194de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 195b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno/** 196b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno * setup_areas - Map the spu regions into the address space. 197b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno * 198b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno * The current HV requires the spu shadow regs to be mapped with the 199b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno * PTE page protection bits set as read-only (PP=3). This implementation 200b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno * uses the low level __ioremap() to bypass the page protection settings 20140f1ce7fb7e8b5d4d0821c0f3dc866cb1d47d99cAnton Blanchard * inforced by ioremap_prot() to get the needed PTE bits set for the 202b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno * shadow regs. 203b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno */ 204b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno 205de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init setup_areas(struct spu *spu) 206de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 207de91a53429952875740692d1de36ae70d4cf81daGeoff Levand struct table {char* name; unsigned long addr; unsigned long size;}; 208b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno static const unsigned long shadow_flags = _PAGE_NO_CACHE | 3; 209de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 210b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno spu_pdata(spu)->shadow = __ioremap(spu_pdata(spu)->shadow_addr, 211b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno sizeof(struct spe_shadow), 212b47027795a22fe61f93de6010c120f26273fc693Masakazu Mokuno shadow_flags); 213de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (!spu_pdata(spu)->shadow) { 214de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__); 215de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_ioremap; 216de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 217de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 21840f1ce7fb7e8b5d4d0821c0f3dc866cb1d47d99cAnton Blanchard spu->local_store = (__force void *)ioremap_prot(spu->local_store_phys, 21953f7c5453dfd3ba66a2d80bd2fda98a2438c3dc0Geoff Levand LS_SIZE, _PAGE_NO_CACHE); 22053f7c5453dfd3ba66a2d80bd2fda98a2438c3dc0Geoff Levand 221de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (!spu->local_store) { 222de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: ioremap local_store failed\n", 223de91a53429952875740692d1de36ae70d4cf81daGeoff Levand __func__, __LINE__); 224de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_ioremap; 225de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 226de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 227de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->problem = ioremap(spu->problem_phys, 228de91a53429952875740692d1de36ae70d4cf81daGeoff Levand sizeof(struct spu_problem)); 22953f7c5453dfd3ba66a2d80bd2fda98a2438c3dc0Geoff Levand 230de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (!spu->problem) { 231de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__); 232de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_ioremap; 233de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 234de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 235de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr, 236de91a53429952875740692d1de36ae70d4cf81daGeoff Levand sizeof(struct spu_priv2)); 23753f7c5453dfd3ba66a2d80bd2fda98a2438c3dc0Geoff Levand 238de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (!spu->priv2) { 239de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__); 240de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_ioremap; 241de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 242de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 243de91a53429952875740692d1de36ae70d4cf81daGeoff Levand dump_areas(spu_pdata(spu)->spe_id, spu_pdata(spu)->priv2_addr, 244de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->problem_phys, spu->local_store_phys, 245de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->shadow_addr); 246de91a53429952875740692d1de36ae70d4cf81daGeoff Levand dump_areas(spu_pdata(spu)->spe_id, (unsigned long)spu->priv2, 247de91a53429952875740692d1de36ae70d4cf81daGeoff Levand (unsigned long)spu->problem, (unsigned long)spu->local_store, 248de91a53429952875740692d1de36ae70d4cf81daGeoff Levand (unsigned long)spu_pdata(spu)->shadow); 249de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 250de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return 0; 251de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 252de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_ioremap: 253de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_unmap(spu); 25444430e0d3916ab6aaf0451fdb811f4f1803b741eBenjamin Herrenschmidt 25544430e0d3916ab6aaf0451fdb811f4f1803b741eBenjamin Herrenschmidt return -ENOMEM; 256de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 257de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 258de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init setup_interrupts(struct spu *spu) 259de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 260de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 261de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 262dc4f60c25ae71e8278dcf909486e4aa34de7eecbGeoff Levand result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 263861be32ce7f1cf272a3f809e77213b83117a0bd2Geoff Levand 0, &spu->irqs[0]); 264de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 265de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 266de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_alloc_0; 267de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 268dc4f60c25ae71e8278dcf909486e4aa34de7eecbGeoff Levand result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 269861be32ce7f1cf272a3f809e77213b83117a0bd2Geoff Levand 1, &spu->irqs[1]); 270de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 271de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 272de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_alloc_1; 273de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 274dc4f60c25ae71e8278dcf909486e4aa34de7eecbGeoff Levand result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 275861be32ce7f1cf272a3f809e77213b83117a0bd2Geoff Levand 2, &spu->irqs[2]); 276de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 277de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 278de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_alloc_2; 279de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 280de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 281de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 282de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_alloc_2: 283dc4f60c25ae71e8278dcf909486e4aa34de7eecbGeoff Levand ps3_spe_irq_destroy(spu->irqs[1]); 284de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_alloc_1: 285dc4f60c25ae71e8278dcf909486e4aa34de7eecbGeoff Levand ps3_spe_irq_destroy(spu->irqs[0]); 286de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_alloc_0: 287de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; 288de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 289de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 290de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 291de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init enable_spu(struct spu *spu) 292de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 293de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 294de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 295de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = lv1_enable_logical_spe(spu_pdata(spu)->spe_id, 296de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->resource_id); 297de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 298de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) { 299de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: lv1_enable_logical_spe failed: %s\n", 300de91a53429952875740692d1de36ae70d4cf81daGeoff Levand __func__, __LINE__, ps3_result(result)); 301de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_enable; 302de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 303de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 304de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = setup_areas(spu); 305de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 306de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 307de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_areas; 308de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 309de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = setup_interrupts(spu); 310de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 311de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 312de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_interrupts; 313de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 314de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return 0; 315de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 316de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_interrupts: 317de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_unmap(spu); 318de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_areas: 319de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0); 320de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_enable: 321de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 322de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 323de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 324de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int ps3_destroy_spu(struct spu *spu) 325de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 326de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 327de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 328de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d spu_%d\n", __func__, __LINE__, spu->number); 329de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 330de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0); 331de91a53429952875740692d1de36ae70d4cf81daGeoff Levand BUG_ON(result); 332de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 333dc4f60c25ae71e8278dcf909486e4aa34de7eecbGeoff Levand ps3_spe_irq_destroy(spu->irqs[2]); 334dc4f60c25ae71e8278dcf909486e4aa34de7eecbGeoff Levand ps3_spe_irq_destroy(spu->irqs[1]); 335dc4f60c25ae71e8278dcf909486e4aa34de7eecbGeoff Levand ps3_spe_irq_destroy(spu->irqs[0]); 336de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 337de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; 338de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 339de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_unmap(spu); 340de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 341de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = lv1_destruct_logical_spe(spu_pdata(spu)->spe_id); 342de91a53429952875740692d1de36ae70d4cf81daGeoff Levand BUG_ON(result); 343de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 344de91a53429952875740692d1de36ae70d4cf81daGeoff Levand kfree(spu->pdata); 345de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->pdata = NULL; 346de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 347de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return 0; 348de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 349de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 350de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init ps3_create_spu(struct spu *spu, void *data) 351de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 352de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 353de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 354de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d spu_%d\n", __func__, __LINE__, spu->number); 355de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 356de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->pdata = kzalloc(sizeof(struct spu_pdata), 357de91a53429952875740692d1de36ae70d4cf81daGeoff Levand GFP_KERNEL); 358de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 359de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (!spu->pdata) { 360de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = -ENOMEM; 361de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_malloc; 362de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 363de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 364de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->resource_id = (unsigned long)data; 365de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 366de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Init cached reg values to HV defaults. */ 367de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 368de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.sr1 = 0x33; 369de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 370de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = construct_spu(spu); 371de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 372de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 373de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_construct; 374de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 375de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* For now, just go ahead and enable it. */ 376de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 377de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = enable_spu(spu); 378de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 379de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 380de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_enable; 381de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 382de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Make sure the spu is in SPE_EX_STATE_EXECUTED. */ 383de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 384de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* need something better here!!! */ 385de91a53429952875740692d1de36ae70d4cf81daGeoff Levand while (in_be64(&spu_pdata(spu)->shadow->spe_execution_status) 386de91a53429952875740692d1de36ae70d4cf81daGeoff Levand != SPE_EX_STATE_EXECUTED) 387de91a53429952875740692d1de36ae70d4cf81daGeoff Levand (void)0; 388de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 389de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 390de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 391de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_enable: 392de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_construct: 393de91a53429952875740692d1de36ae70d4cf81daGeoff Levand ps3_destroy_spu(spu); 394de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_malloc: 395de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 396de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 397de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 398de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init ps3_enumerate_spus(int (*fn)(void *data)) 399de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 400de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 401de91a53429952875740692d1de36ae70d4cf81daGeoff Levand unsigned int num_resource_id; 402de91a53429952875740692d1de36ae70d4cf81daGeoff Levand unsigned int i; 403de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 404de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = ps3_repository_read_num_spu_resource_id(&num_resource_id); 405de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 406de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: num_resource_id %u\n", __func__, __LINE__, 407de91a53429952875740692d1de36ae70d4cf81daGeoff Levand num_resource_id); 408de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 409de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* 410de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * For now, just create logical spus equal to the number 411de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * of physical spus reserved for the partition. 412de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 413de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 414de91a53429952875740692d1de36ae70d4cf81daGeoff Levand for (i = 0; i < num_resource_id; i++) { 415de91a53429952875740692d1de36ae70d4cf81daGeoff Levand enum ps3_spu_resource_type resource_type; 416de91a53429952875740692d1de36ae70d4cf81daGeoff Levand unsigned int resource_id; 417de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 418de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = ps3_repository_read_spu_resource_id(i, 419de91a53429952875740692d1de36ae70d4cf81daGeoff Levand &resource_type, &resource_id); 420de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 421de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 422de91a53429952875740692d1de36ae70d4cf81daGeoff Levand break; 423de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 424de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (resource_type == PS3_SPU_RESOURCE_TYPE_EXCLUSIVE) { 425de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = fn((void*)(unsigned long)resource_id); 426de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 427de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 428de91a53429952875740692d1de36ae70d4cf81daGeoff Levand break; 429de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 430de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 431de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 432bce9451310eb66fbbd77bf22e8160079700691f8Geert Uytterhoeven if (result) { 433de91a53429952875740692d1de36ae70d4cf81daGeoff Levand printk(KERN_WARNING "%s:%d: Error initializing spus\n", 434de91a53429952875740692d1de36ae70d4cf81daGeoff Levand __func__, __LINE__); 435bce9451310eb66fbbd77bf22e8160079700691f8Geert Uytterhoeven return result; 436bce9451310eb66fbbd77bf22e8160079700691f8Geert Uytterhoeven } 437de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 438bce9451310eb66fbbd77bf22e8160079700691f8Geert Uytterhoeven return num_resource_id; 439de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 440de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 441f5996449e3244524cab0ba709a4bd87047a8175fAndre Detschstatic int ps3_init_affinity(void) 442f5996449e3244524cab0ba709a4bd87047a8175fAndre Detsch{ 443f5996449e3244524cab0ba709a4bd87047a8175fAndre Detsch return 0; 444f5996449e3244524cab0ba709a4bd87047a8175fAndre Detsch} 445f5996449e3244524cab0ba709a4bd87047a8175fAndre Detsch 446c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi/** 447c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi * ps3_enable_spu - Enable SPU run control. 448c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi * 449c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi * An outstanding enhancement for the PS3 would be to add a guard to check 450c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi * for incorrect access to the spu problem state when the spu context is 451c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi * disabled. This check could be implemented with a flag added to the spu 452c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi * context that would inhibit mapping problem state pages, and a routine 453c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi * to unmap spu problem state pages. When the spu is enabled with 454c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi * ps3_enable_spu() the flag would be set allowing pages to be mapped, 455c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi * and when the spu is disabled with ps3_disable_spu() the flag would be 456c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi * cleared and the mapped problem state pages would be unmapped. 457c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi */ 458c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi 459c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchistatic void ps3_enable_spu(struct spu_context *ctx) 460c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi{ 461c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi} 462c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi 463c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchistatic void ps3_disable_spu(struct spu_context *ctx) 464c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi{ 465c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi ctx->ops->runcntl_stop(ctx); 466c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi} 467c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi 468de91a53429952875740692d1de36ae70d4cf81daGeoff Levandconst struct spu_management_ops spu_management_ps3_ops = { 469de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .enumerate_spus = ps3_enumerate_spus, 470de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .create_spu = ps3_create_spu, 471de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .destroy_spu = ps3_destroy_spu, 472c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi .enable_spu = ps3_enable_spu, 473c25620d7663fef41c373d42c4923c1d6b9847684Masato Noguchi .disable_spu = ps3_disable_spu, 474f5996449e3244524cab0ba709a4bd87047a8175fAndre Detsch .init_affinity = ps3_init_affinity, 475de91a53429952875740692d1de36ae70d4cf81daGeoff Levand}; 476de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 477de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/* spu_priv1_ops */ 478de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 479de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void int_mask_and(struct spu *spu, int class, u64 mask) 480de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 481de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 old_mask; 482de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 483de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* are these serialized by caller??? */ 484de91a53429952875740692d1de36ae70d4cf81daGeoff Levand old_mask = spu_int_mask_get(spu, class); 485de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_int_mask_set(spu, class, old_mask & mask); 486de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 487de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 488de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void int_mask_or(struct spu *spu, int class, u64 mask) 489de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 490de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 old_mask; 491de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 492de91a53429952875740692d1de36ae70d4cf81daGeoff Levand old_mask = spu_int_mask_get(spu, class); 493de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_int_mask_set(spu, class, old_mask | mask); 494de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 495de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 496de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void int_mask_set(struct spu *spu, int class, u64 mask) 497de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 498de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.masks[class] = mask; 499de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_set_spe_interrupt_mask(spu_pdata(spu)->spe_id, class, 500de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.masks[class]); 501de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 502de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 503de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 int_mask_get(struct spu *spu, int class) 504de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 505de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return spu_pdata(spu)->cache.masks[class]; 506de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 507de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 508de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void int_stat_clear(struct spu *spu, int class, u64 stat) 509de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 510de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Note that MFC_DSISR will be cleared when class1[MF] is set. */ 511de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 512de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_clear_spe_interrupt_status(spu_pdata(spu)->spe_id, class, 513de91a53429952875740692d1de36ae70d4cf81daGeoff Levand stat, 0); 514de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 515de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 516de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 int_stat_get(struct spu *spu, int class) 517de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 518de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 stat; 519de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 520de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_get_spe_interrupt_status(spu_pdata(spu)->spe_id, class, &stat); 521de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return stat; 522de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 523de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 524de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void cpu_affinity_set(struct spu *spu, int cpu) 525de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 526de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* No support. */ 527de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 528de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 529de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 mfc_dar_get(struct spu *spu) 530de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 531de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return in_be64(&spu_pdata(spu)->shadow->mfc_dar_RW); 532de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 533de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 534de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void mfc_dsisr_set(struct spu *spu, u64 dsisr) 535de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 536de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Nothing to do, cleared in int_stat_clear(). */ 537de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 538de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 539de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 mfc_dsisr_get(struct spu *spu) 540de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 541de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return in_be64(&spu_pdata(spu)->shadow->mfc_dsisr_RW); 542de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 543de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 544de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void mfc_sdr_setup(struct spu *spu) 545de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 546de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Nothing to do. */ 547de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 548de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 549de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void mfc_sr1_set(struct spu *spu, u64 sr1) 550de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 551de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Check bits allowed by HV. */ 552de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 553de91a53429952875740692d1de36ae70d4cf81daGeoff Levand static const u64 allowed = ~(MFC_STATE1_LOCAL_STORAGE_DECODE_MASK 554de91a53429952875740692d1de36ae70d4cf81daGeoff Levand | MFC_STATE1_PROBLEM_STATE_MASK); 555de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 556de91a53429952875740692d1de36ae70d4cf81daGeoff Levand BUG_ON((sr1 & allowed) != (spu_pdata(spu)->cache.sr1 & allowed)); 557de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 558de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.sr1 = sr1; 559de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_set_spe_privilege_state_area_1_register( 560de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->spe_id, 561de91a53429952875740692d1de36ae70d4cf81daGeoff Levand offsetof(struct spu_priv1, mfc_sr1_RW), 562de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.sr1); 563de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 564de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 565de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 mfc_sr1_get(struct spu *spu) 566de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 567de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return spu_pdata(spu)->cache.sr1; 568de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 569de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 570de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void mfc_tclass_id_set(struct spu *spu, u64 tclass_id) 571de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 572de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.tclass_id = tclass_id; 573de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_set_spe_privilege_state_area_1_register( 574de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->spe_id, 575de91a53429952875740692d1de36ae70d4cf81daGeoff Levand offsetof(struct spu_priv1, mfc_tclass_id_RW), 576de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.tclass_id); 577de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 578de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 579de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 mfc_tclass_id_get(struct spu *spu) 580de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 581de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return spu_pdata(spu)->cache.tclass_id; 582de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 583de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 584de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void tlb_invalidate(struct spu *spu) 585de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 586de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Nothing to do. */ 587de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 588de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 589de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void resource_allocation_groupID_set(struct spu *spu, u64 id) 590de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 591de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* No support. */ 592de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 593de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 594de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 resource_allocation_groupID_get(struct spu *spu) 595de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 596de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return 0; /* No support. */ 597de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 598de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 599de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void resource_allocation_enable_set(struct spu *spu, u64 enable) 600de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 601de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* No support. */ 602de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 603de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 604de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 resource_allocation_enable_get(struct spu *spu) 605de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 606de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return 0; /* No support. */ 607de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 608de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 609de91a53429952875740692d1de36ae70d4cf81daGeoff Levandconst struct spu_priv1_ops spu_priv1_ps3_ops = { 610de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .int_mask_and = int_mask_and, 611de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .int_mask_or = int_mask_or, 612de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .int_mask_set = int_mask_set, 613de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .int_mask_get = int_mask_get, 614de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .int_stat_clear = int_stat_clear, 615de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .int_stat_get = int_stat_get, 616de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .cpu_affinity_set = cpu_affinity_set, 617de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_dar_get = mfc_dar_get, 618de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_dsisr_set = mfc_dsisr_set, 619de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_dsisr_get = mfc_dsisr_get, 620de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_sdr_setup = mfc_sdr_setup, 621de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_sr1_set = mfc_sr1_set, 622de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_sr1_get = mfc_sr1_get, 623de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_tclass_id_set = mfc_tclass_id_set, 624de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_tclass_id_get = mfc_tclass_id_get, 625de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .tlb_invalidate = tlb_invalidate, 626de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .resource_allocation_groupID_set = resource_allocation_groupID_set, 627de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .resource_allocation_groupID_get = resource_allocation_groupID_get, 628de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .resource_allocation_enable_set = resource_allocation_enable_set, 629de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .resource_allocation_enable_get = resource_allocation_enable_get, 630de91a53429952875740692d1de36ae70d4cf81daGeoff Levand}; 631de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 632de91a53429952875740692d1de36ae70d4cf81daGeoff Levandvoid ps3_spu_set_platform(void) 633de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 634de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_priv1_ops = &spu_priv1_ps3_ops; 635de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_management_ops = &spu_management_ps3_ops; 636de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 637