spu.c revision de91a53429952875740692d1de36ae70d4cf81da
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> 23de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <linux/mmzone.h> 24de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <linux/io.h> 25de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <linux/mm.h> 26de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 27de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <asm/spu.h> 28de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <asm/spu_priv1.h> 29de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <asm/ps3.h> 30de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#include <asm/lv1call.h> 31de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 32de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/* spu_management_ops */ 33de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 34de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/** 35de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * enum spe_type - Type of spe to create. 36de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @spe_type_logical: Standard logical spe. 37de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * 38de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * For use with lv1_construct_logical_spe(). The current HV does not support 39de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * any types other than those listed. 40de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 41de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 42de91a53429952875740692d1de36ae70d4cf81daGeoff Levandenum spe_type { 43de91a53429952875740692d1de36ae70d4cf81daGeoff Levand SPE_TYPE_LOGICAL = 0, 44de91a53429952875740692d1de36ae70d4cf81daGeoff Levand}; 45de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 46de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/** 47de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * struct spe_shadow - logical spe shadow register area. 48de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * 49de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * Read-only shadow of spe registers. 50de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 51de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 52de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstruct spe_shadow { 53de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0000[0x0140]; 54de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 int_status_class0_RW; /* 0x0140 */ 55de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 int_status_class1_RW; /* 0x0148 */ 56de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 int_status_class2_RW; /* 0x0150 */ 57de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0158[0x0610-0x0158]; 58de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 mfc_dsisr_RW; /* 0x0610 */ 59de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0618[0x0620-0x0618]; 60de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 mfc_dar_RW; /* 0x0620 */ 61de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0628[0x0800-0x0628]; 62de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 mfc_dsipr_R; /* 0x0800 */ 63de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0808[0x0810-0x0808]; 64de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 mfc_lscrr_R; /* 0x0810 */ 65de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0818[0x0c00-0x0818]; 66de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 mfc_cer_R; /* 0x0c00 */ 67de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0c08[0x0f00-0x0c08]; 68de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 spe_execution_status; /* 0x0f00 */ 69de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u8 padding_0f08[0x1000-0x0f08]; 70de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} __attribute__ ((packed)); 71de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 72de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 73de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/** 74de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * enum spe_ex_state - Logical spe execution state. 75de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @spe_ex_state_unexecutable: Uninitialized. 76de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @spe_ex_state_executable: Enabled, not ready. 77de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @spe_ex_state_executed: Ready for use. 78de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * 79de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * The execution state (status) of the logical spe as reported in 80de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * struct spe_shadow:spe_execution_status. 81de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 82de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 83de91a53429952875740692d1de36ae70d4cf81daGeoff Levandenum spe_ex_state { 84de91a53429952875740692d1de36ae70d4cf81daGeoff Levand SPE_EX_STATE_UNEXECUTABLE = 0, 85de91a53429952875740692d1de36ae70d4cf81daGeoff Levand SPE_EX_STATE_EXECUTABLE = 2, 86de91a53429952875740692d1de36ae70d4cf81daGeoff Levand SPE_EX_STATE_EXECUTED = 3, 87de91a53429952875740692d1de36ae70d4cf81daGeoff Levand}; 88de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 89de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/** 90de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * struct priv1_cache - Cached values of priv1 registers. 91de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @masks[]: Array of cached spe interrupt masks, indexed by class. 92de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @sr1: Cached mfc_sr1 register. 93de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @tclass_id: Cached mfc_tclass_id register. 94de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 95de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 96de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstruct priv1_cache { 97de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 masks[3]; 98de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 sr1; 99de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 tclass_id; 100de91a53429952875740692d1de36ae70d4cf81daGeoff Levand}; 101de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 102de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/** 103de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * struct spu_pdata - Platform state variables. 104de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @spe_id: HV spe id returned by lv1_construct_logical_spe(). 105de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @resource_id: HV spe resource id returned by 106de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * ps3_repository_read_spe_resource_id(). 107de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @priv2_addr: lpar address of spe priv2 area returned by 108de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * lv1_construct_logical_spe(). 109de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @shadow_addr: lpar address of spe register shadow area returned by 110de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * lv1_construct_logical_spe(). 111de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @shadow: Virtual (ioremap) address of spe register shadow area. 112de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * @cache: Cached values of priv1 registers. 113de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 114de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 115de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstruct spu_pdata { 116de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 spe_id; 117de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 resource_id; 118de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 priv2_addr; 119de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 shadow_addr; 120de91a53429952875740692d1de36ae70d4cf81daGeoff Levand struct spe_shadow __iomem *shadow; 121de91a53429952875740692d1de36ae70d4cf81daGeoff Levand struct priv1_cache cache; 122de91a53429952875740692d1de36ae70d4cf81daGeoff Levand}; 123de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 124de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic struct spu_pdata *spu_pdata(struct spu *spu) 125de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 126de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return spu->pdata; 127de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 128de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 129de91a53429952875740692d1de36ae70d4cf81daGeoff Levand#define dump_areas(_a, _b, _c, _d, _e) \ 130de91a53429952875740692d1de36ae70d4cf81daGeoff Levand _dump_areas(_a, _b, _c, _d, _e, __func__, __LINE__) 131de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void _dump_areas(unsigned int spe_id, unsigned long priv2, 132de91a53429952875740692d1de36ae70d4cf81daGeoff Levand unsigned long problem, unsigned long ls, unsigned long shadow, 133de91a53429952875740692d1de36ae70d4cf81daGeoff Levand const char* func, int line) 134de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 135de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: spe_id: %xh (%u)\n", func, line, spe_id, spe_id); 136de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: priv2: %lxh\n", func, line, priv2); 137de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: problem: %lxh\n", func, line, problem); 138de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: ls: %lxh\n", func, line, ls); 139de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: shadow: %lxh\n", func, line, shadow); 140de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 141de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 142de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic unsigned long get_vas_id(void) 143de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 144de91a53429952875740692d1de36ae70d4cf81daGeoff Levand unsigned long id; 145de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 146de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_get_logical_ppe_id(&id); 147de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_get_virtual_address_space_id_of_ppe(id, &id); 148de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 149de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return id; 150de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 151de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 152de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init construct_spu(struct spu *spu) 153de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 154de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 155de91a53429952875740692d1de36ae70d4cf81daGeoff Levand unsigned long unused; 156de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 157de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = lv1_construct_logical_spe(PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT, 158de91a53429952875740692d1de36ae70d4cf81daGeoff Levand PAGE_SHIFT, PAGE_SHIFT, get_vas_id(), SPE_TYPE_LOGICAL, 159de91a53429952875740692d1de36ae70d4cf81daGeoff Levand &spu_pdata(spu)->priv2_addr, &spu->problem_phys, 160de91a53429952875740692d1de36ae70d4cf81daGeoff Levand &spu->local_store_phys, &unused, 161de91a53429952875740692d1de36ae70d4cf81daGeoff Levand &spu_pdata(spu)->shadow_addr, 162de91a53429952875740692d1de36ae70d4cf81daGeoff Levand &spu_pdata(spu)->spe_id); 163de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 164de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) { 165de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: lv1_construct_logical_spe failed: %s\n", 166de91a53429952875740692d1de36ae70d4cf81daGeoff Levand __func__, __LINE__, ps3_result(result)); 167de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 168de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 169de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 170de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 171de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 172de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 173de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init add_spu_pages(unsigned long start_addr, unsigned long size) 174de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 175de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 176de91a53429952875740692d1de36ae70d4cf81daGeoff Levand unsigned long start_pfn; 177de91a53429952875740692d1de36ae70d4cf81daGeoff Levand unsigned long nr_pages; 178de91a53429952875740692d1de36ae70d4cf81daGeoff Levand struct pglist_data *pgdata; 179de91a53429952875740692d1de36ae70d4cf81daGeoff Levand struct zone *zone; 180de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 181de91a53429952875740692d1de36ae70d4cf81daGeoff Levand BUG_ON(!mem_init_done); 182de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 183de91a53429952875740692d1de36ae70d4cf81daGeoff Levand start_pfn = start_addr >> PAGE_SHIFT; 184de91a53429952875740692d1de36ae70d4cf81daGeoff Levand nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; 185de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 186de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pgdata = NODE_DATA(0); 187de91a53429952875740692d1de36ae70d4cf81daGeoff Levand zone = pgdata->node_zones; 188de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 189de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = __add_pages(zone, start_pfn, nr_pages); 190de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 191de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 192de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: __add_pages failed: (%d)\n", 193de91a53429952875740692d1de36ae70d4cf81daGeoff Levand __func__, __LINE__, result); 194de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 195de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 196de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 197de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 198de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void spu_unmap(struct spu *spu) 199de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 200de91a53429952875740692d1de36ae70d4cf81daGeoff Levand iounmap(spu->priv2); 201de91a53429952875740692d1de36ae70d4cf81daGeoff Levand iounmap(spu->problem); 202de91a53429952875740692d1de36ae70d4cf81daGeoff Levand iounmap((__force u8 __iomem *)spu->local_store); 203de91a53429952875740692d1de36ae70d4cf81daGeoff Levand iounmap(spu_pdata(spu)->shadow); 204de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 205de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 206de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init setup_areas(struct spu *spu) 207de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 208de91a53429952875740692d1de36ae70d4cf81daGeoff Levand struct table {char* name; unsigned long addr; unsigned long size;}; 209de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 210de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 211de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* setup pages */ 212de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 213de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = add_spu_pages(spu->local_store_phys, LS_SIZE); 214de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 215de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_add; 216de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 217de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = add_spu_pages(spu->problem_phys, sizeof(struct spu_problem)); 218de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 219de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_add; 220de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 221de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* ioremap */ 222de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 223de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->shadow = __ioremap( 224de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow), 225de91a53429952875740692d1de36ae70d4cf81daGeoff Levand PAGE_READONLY | _PAGE_NO_CACHE | _PAGE_GUARDED); 226de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (!spu_pdata(spu)->shadow) { 227de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__); 228de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_ioremap; 229de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 230de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 231de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->local_store = ioremap(spu->local_store_phys, LS_SIZE); 232de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (!spu->local_store) { 233de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: ioremap local_store failed\n", 234de91a53429952875740692d1de36ae70d4cf81daGeoff Levand __func__, __LINE__); 235de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_ioremap; 236de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 237de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 238de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->problem = ioremap(spu->problem_phys, 239de91a53429952875740692d1de36ae70d4cf81daGeoff Levand sizeof(struct spu_problem)); 240de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (!spu->problem) { 241de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__); 242de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_ioremap; 243de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 244de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 245de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr, 246de91a53429952875740692d1de36ae70d4cf81daGeoff Levand sizeof(struct spu_priv2)); 247de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (!spu->priv2) { 248de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__); 249de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_ioremap; 250de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 251de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 252de91a53429952875740692d1de36ae70d4cf81daGeoff Levand dump_areas(spu_pdata(spu)->spe_id, spu_pdata(spu)->priv2_addr, 253de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->problem_phys, spu->local_store_phys, 254de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->shadow_addr); 255de91a53429952875740692d1de36ae70d4cf81daGeoff Levand dump_areas(spu_pdata(spu)->spe_id, (unsigned long)spu->priv2, 256de91a53429952875740692d1de36ae70d4cf81daGeoff Levand (unsigned long)spu->problem, (unsigned long)spu->local_store, 257de91a53429952875740692d1de36ae70d4cf81daGeoff Levand (unsigned long)spu_pdata(spu)->shadow); 258de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 259de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return 0; 260de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 261de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_ioremap: 262de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_unmap(spu); 263de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_add: 264de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 265de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 266de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 267de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init setup_interrupts(struct spu *spu) 268de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 269de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 270de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 271de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = ps3_alloc_spe_irq(spu_pdata(spu)->spe_id, 0, 272de91a53429952875740692d1de36ae70d4cf81daGeoff Levand &spu->irqs[0]); 273de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 274de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 275de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_alloc_0; 276de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 277de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = ps3_alloc_spe_irq(spu_pdata(spu)->spe_id, 1, 278de91a53429952875740692d1de36ae70d4cf81daGeoff Levand &spu->irqs[1]); 279de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 280de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 281de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_alloc_1; 282de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 283de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = ps3_alloc_spe_irq(spu_pdata(spu)->spe_id, 2, 284de91a53429952875740692d1de36ae70d4cf81daGeoff Levand &spu->irqs[2]); 285de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 286de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 287de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_alloc_2; 288de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 289de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 290de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 291de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_alloc_2: 292de91a53429952875740692d1de36ae70d4cf81daGeoff Levand ps3_free_spe_irq(spu->irqs[1]); 293de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_alloc_1: 294de91a53429952875740692d1de36ae70d4cf81daGeoff Levand ps3_free_spe_irq(spu->irqs[0]); 295de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_alloc_0: 296de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; 297de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 298de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 299de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 300de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init enable_spu(struct spu *spu) 301de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 302de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 303de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 304de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = lv1_enable_logical_spe(spu_pdata(spu)->spe_id, 305de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->resource_id); 306de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 307de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) { 308de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: lv1_enable_logical_spe failed: %s\n", 309de91a53429952875740692d1de36ae70d4cf81daGeoff Levand __func__, __LINE__, ps3_result(result)); 310de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_enable; 311de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 312de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 313de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = setup_areas(spu); 314de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 315de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 316de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_areas; 317de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 318de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = setup_interrupts(spu); 319de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 320de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 321de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_interrupts; 322de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 323de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return 0; 324de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 325de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_interrupts: 326de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_unmap(spu); 327de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_areas: 328de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0); 329de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_enable: 330de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 331de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 332de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 333de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int ps3_destroy_spu(struct spu *spu) 334de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 335de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 336de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 337de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d spu_%d\n", __func__, __LINE__, spu->number); 338de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 339de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0); 340de91a53429952875740692d1de36ae70d4cf81daGeoff Levand BUG_ON(result); 341de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 342de91a53429952875740692d1de36ae70d4cf81daGeoff Levand ps3_free_spe_irq(spu->irqs[2]); 343de91a53429952875740692d1de36ae70d4cf81daGeoff Levand ps3_free_spe_irq(spu->irqs[1]); 344de91a53429952875740692d1de36ae70d4cf81daGeoff Levand ps3_free_spe_irq(spu->irqs[0]); 345de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 346de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; 347de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 348de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_unmap(spu); 349de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 350de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = lv1_destruct_logical_spe(spu_pdata(spu)->spe_id); 351de91a53429952875740692d1de36ae70d4cf81daGeoff Levand BUG_ON(result); 352de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 353de91a53429952875740692d1de36ae70d4cf81daGeoff Levand kfree(spu->pdata); 354de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->pdata = NULL; 355de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 356de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return 0; 357de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 358de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 359de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init ps3_create_spu(struct spu *spu, void *data) 360de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 361de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 362de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 363de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d spu_%d\n", __func__, __LINE__, spu->number); 364de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 365de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu->pdata = kzalloc(sizeof(struct spu_pdata), 366de91a53429952875740692d1de36ae70d4cf81daGeoff Levand GFP_KERNEL); 367de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 368de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (!spu->pdata) { 369de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = -ENOMEM; 370de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_malloc; 371de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 372de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 373de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->resource_id = (unsigned long)data; 374de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 375de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Init cached reg values to HV defaults. */ 376de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 377de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.sr1 = 0x33; 378de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 379de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = construct_spu(spu); 380de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 381de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 382de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_construct; 383de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 384de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* For now, just go ahead and enable it. */ 385de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 386de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = enable_spu(spu); 387de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 388de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 389de91a53429952875740692d1de36ae70d4cf81daGeoff Levand goto fail_enable; 390de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 391de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Make sure the spu is in SPE_EX_STATE_EXECUTED. */ 392de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 393de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* need something better here!!! */ 394de91a53429952875740692d1de36ae70d4cf81daGeoff Levand while (in_be64(&spu_pdata(spu)->shadow->spe_execution_status) 395de91a53429952875740692d1de36ae70d4cf81daGeoff Levand != SPE_EX_STATE_EXECUTED) 396de91a53429952875740692d1de36ae70d4cf81daGeoff Levand (void)0; 397de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 398de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 399de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 400de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_enable: 401de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_construct: 402de91a53429952875740692d1de36ae70d4cf81daGeoff Levand ps3_destroy_spu(spu); 403de91a53429952875740692d1de36ae70d4cf81daGeoff Levandfail_malloc: 404de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 405de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 406de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 407de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic int __init ps3_enumerate_spus(int (*fn)(void *data)) 408de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 409de91a53429952875740692d1de36ae70d4cf81daGeoff Levand int result; 410de91a53429952875740692d1de36ae70d4cf81daGeoff Levand unsigned int num_resource_id; 411de91a53429952875740692d1de36ae70d4cf81daGeoff Levand unsigned int i; 412de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 413de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = ps3_repository_read_num_spu_resource_id(&num_resource_id); 414de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 415de91a53429952875740692d1de36ae70d4cf81daGeoff Levand pr_debug("%s:%d: num_resource_id %u\n", __func__, __LINE__, 416de91a53429952875740692d1de36ae70d4cf81daGeoff Levand num_resource_id); 417de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 418de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* 419de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * For now, just create logical spus equal to the number 420de91a53429952875740692d1de36ae70d4cf81daGeoff Levand * of physical spus reserved for the partition. 421de91a53429952875740692d1de36ae70d4cf81daGeoff Levand */ 422de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 423de91a53429952875740692d1de36ae70d4cf81daGeoff Levand for (i = 0; i < num_resource_id; i++) { 424de91a53429952875740692d1de36ae70d4cf81daGeoff Levand enum ps3_spu_resource_type resource_type; 425de91a53429952875740692d1de36ae70d4cf81daGeoff Levand unsigned int resource_id; 426de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 427de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = ps3_repository_read_spu_resource_id(i, 428de91a53429952875740692d1de36ae70d4cf81daGeoff Levand &resource_type, &resource_id); 429de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 430de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 431de91a53429952875740692d1de36ae70d4cf81daGeoff Levand break; 432de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 433de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (resource_type == PS3_SPU_RESOURCE_TYPE_EXCLUSIVE) { 434de91a53429952875740692d1de36ae70d4cf81daGeoff Levand result = fn((void*)(unsigned long)resource_id); 435de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 436de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 437de91a53429952875740692d1de36ae70d4cf81daGeoff Levand break; 438de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 439de91a53429952875740692d1de36ae70d4cf81daGeoff Levand } 440de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 441de91a53429952875740692d1de36ae70d4cf81daGeoff Levand if (result) 442de91a53429952875740692d1de36ae70d4cf81daGeoff Levand printk(KERN_WARNING "%s:%d: Error initializing spus\n", 443de91a53429952875740692d1de36ae70d4cf81daGeoff Levand __func__, __LINE__); 444de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 445de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return result; 446de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 447de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 448de91a53429952875740692d1de36ae70d4cf81daGeoff Levandconst struct spu_management_ops spu_management_ps3_ops = { 449de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .enumerate_spus = ps3_enumerate_spus, 450de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .create_spu = ps3_create_spu, 451de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .destroy_spu = ps3_destroy_spu, 452de91a53429952875740692d1de36ae70d4cf81daGeoff Levand}; 453de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 454de91a53429952875740692d1de36ae70d4cf81daGeoff Levand/* spu_priv1_ops */ 455de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 456de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void int_mask_and(struct spu *spu, int class, u64 mask) 457de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 458de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 old_mask; 459de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 460de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* are these serialized by caller??? */ 461de91a53429952875740692d1de36ae70d4cf81daGeoff Levand old_mask = spu_int_mask_get(spu, class); 462de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_int_mask_set(spu, class, old_mask & mask); 463de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 464de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 465de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void int_mask_or(struct spu *spu, int class, u64 mask) 466de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 467de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 old_mask; 468de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 469de91a53429952875740692d1de36ae70d4cf81daGeoff Levand old_mask = spu_int_mask_get(spu, class); 470de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_int_mask_set(spu, class, old_mask | mask); 471de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 472de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 473de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void int_mask_set(struct spu *spu, int class, u64 mask) 474de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 475de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.masks[class] = mask; 476de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_set_spe_interrupt_mask(spu_pdata(spu)->spe_id, class, 477de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.masks[class]); 478de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 479de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 480de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 int_mask_get(struct spu *spu, int class) 481de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 482de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return spu_pdata(spu)->cache.masks[class]; 483de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 484de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 485de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void int_stat_clear(struct spu *spu, int class, u64 stat) 486de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 487de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Note that MFC_DSISR will be cleared when class1[MF] is set. */ 488de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 489de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_clear_spe_interrupt_status(spu_pdata(spu)->spe_id, class, 490de91a53429952875740692d1de36ae70d4cf81daGeoff Levand stat, 0); 491de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 492de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 493de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 int_stat_get(struct spu *spu, int class) 494de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 495de91a53429952875740692d1de36ae70d4cf81daGeoff Levand u64 stat; 496de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 497de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_get_spe_interrupt_status(spu_pdata(spu)->spe_id, class, &stat); 498de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return stat; 499de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 500de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 501de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void cpu_affinity_set(struct spu *spu, int cpu) 502de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 503de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* No support. */ 504de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 505de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 506de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 mfc_dar_get(struct spu *spu) 507de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 508de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return in_be64(&spu_pdata(spu)->shadow->mfc_dar_RW); 509de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 510de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 511de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void mfc_dsisr_set(struct spu *spu, u64 dsisr) 512de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 513de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Nothing to do, cleared in int_stat_clear(). */ 514de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 515de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 516de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 mfc_dsisr_get(struct spu *spu) 517de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 518de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return in_be64(&spu_pdata(spu)->shadow->mfc_dsisr_RW); 519de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 520de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 521de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void mfc_sdr_setup(struct spu *spu) 522de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 523de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Nothing to do. */ 524de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 525de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 526de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void mfc_sr1_set(struct spu *spu, u64 sr1) 527de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 528de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Check bits allowed by HV. */ 529de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 530de91a53429952875740692d1de36ae70d4cf81daGeoff Levand static const u64 allowed = ~(MFC_STATE1_LOCAL_STORAGE_DECODE_MASK 531de91a53429952875740692d1de36ae70d4cf81daGeoff Levand | MFC_STATE1_PROBLEM_STATE_MASK); 532de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 533de91a53429952875740692d1de36ae70d4cf81daGeoff Levand BUG_ON((sr1 & allowed) != (spu_pdata(spu)->cache.sr1 & allowed)); 534de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 535de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.sr1 = sr1; 536de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_set_spe_privilege_state_area_1_register( 537de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->spe_id, 538de91a53429952875740692d1de36ae70d4cf81daGeoff Levand offsetof(struct spu_priv1, mfc_sr1_RW), 539de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.sr1); 540de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 541de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 542de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 mfc_sr1_get(struct spu *spu) 543de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 544de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return spu_pdata(spu)->cache.sr1; 545de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 546de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 547de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void mfc_tclass_id_set(struct spu *spu, u64 tclass_id) 548de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 549de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.tclass_id = tclass_id; 550de91a53429952875740692d1de36ae70d4cf81daGeoff Levand lv1_set_spe_privilege_state_area_1_register( 551de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->spe_id, 552de91a53429952875740692d1de36ae70d4cf81daGeoff Levand offsetof(struct spu_priv1, mfc_tclass_id_RW), 553de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_pdata(spu)->cache.tclass_id); 554de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 555de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 556de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 mfc_tclass_id_get(struct spu *spu) 557de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 558de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return spu_pdata(spu)->cache.tclass_id; 559de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 560de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 561de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void tlb_invalidate(struct spu *spu) 562de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 563de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* Nothing to do. */ 564de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 565de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 566de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void resource_allocation_groupID_set(struct spu *spu, u64 id) 567de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 568de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* No support. */ 569de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 570de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 571de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 resource_allocation_groupID_get(struct spu *spu) 572de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 573de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return 0; /* No support. */ 574de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 575de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 576de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic void resource_allocation_enable_set(struct spu *spu, u64 enable) 577de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 578de91a53429952875740692d1de36ae70d4cf81daGeoff Levand /* No support. */ 579de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 580de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 581de91a53429952875740692d1de36ae70d4cf81daGeoff Levandstatic u64 resource_allocation_enable_get(struct spu *spu) 582de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 583de91a53429952875740692d1de36ae70d4cf81daGeoff Levand return 0; /* No support. */ 584de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 585de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 586de91a53429952875740692d1de36ae70d4cf81daGeoff Levandconst struct spu_priv1_ops spu_priv1_ps3_ops = { 587de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .int_mask_and = int_mask_and, 588de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .int_mask_or = int_mask_or, 589de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .int_mask_set = int_mask_set, 590de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .int_mask_get = int_mask_get, 591de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .int_stat_clear = int_stat_clear, 592de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .int_stat_get = int_stat_get, 593de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .cpu_affinity_set = cpu_affinity_set, 594de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_dar_get = mfc_dar_get, 595de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_dsisr_set = mfc_dsisr_set, 596de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_dsisr_get = mfc_dsisr_get, 597de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_sdr_setup = mfc_sdr_setup, 598de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_sr1_set = mfc_sr1_set, 599de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_sr1_get = mfc_sr1_get, 600de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_tclass_id_set = mfc_tclass_id_set, 601de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .mfc_tclass_id_get = mfc_tclass_id_get, 602de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .tlb_invalidate = tlb_invalidate, 603de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .resource_allocation_groupID_set = resource_allocation_groupID_set, 604de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .resource_allocation_groupID_get = resource_allocation_groupID_get, 605de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .resource_allocation_enable_set = resource_allocation_enable_set, 606de91a53429952875740692d1de36ae70d4cf81daGeoff Levand .resource_allocation_enable_get = resource_allocation_enable_get, 607de91a53429952875740692d1de36ae70d4cf81daGeoff Levand}; 608de91a53429952875740692d1de36ae70d4cf81daGeoff Levand 609de91a53429952875740692d1de36ae70d4cf81daGeoff Levandvoid ps3_spu_set_platform(void) 610de91a53429952875740692d1de36ae70d4cf81daGeoff Levand{ 611de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_priv1_ops = &spu_priv1_ps3_ops; 612de91a53429952875740692d1de36ae70d4cf81daGeoff Levand spu_management_ops = &spu_management_ps3_ops; 613de91a53429952875740692d1de36ae70d4cf81daGeoff Levand} 614