Path: blob/master/arch/powerpc/platforms/ps3/repository.c
26481 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* PS3 repository routines.3*4* Copyright (C) 2006 Sony Computer Entertainment Inc.5* Copyright 2006 Sony Corp.6*/78#include <asm/lv1call.h>910#include "platform.h"1112enum ps3_vendor_id {13PS3_VENDOR_ID_NONE = 0,14PS3_VENDOR_ID_SONY = 0x8000000000000000UL,15};1617enum ps3_lpar_id {18PS3_LPAR_ID_CURRENT = 0,19PS3_LPAR_ID_PME = 1,20};2122#define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__)23static void _dump_field(const char *hdr, u64 n, const char *func, int line)24{25#if defined(DEBUG)26char s[16];27const char *const in = (const char *)&n;28unsigned int i;2930for (i = 0; i < 8; i++)31s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.';32s[i] = 0;3334pr_devel("%s:%d: %s%016llx : %s\n", func, line, hdr, n, s);35#endif36}3738#define dump_node_name(_a, _b, _c, _d, _e) \39_dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__)40static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3,41u64 n4, const char *func, int line)42{43pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id);44_dump_field("n1: ", n1, func, line);45_dump_field("n2: ", n2, func, line);46_dump_field("n3: ", n3, func, line);47_dump_field("n4: ", n4, func, line);48}4950#define dump_node(_a, _b, _c, _d, _e, _f, _g) \51_dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)52static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,53u64 v1, u64 v2, const char *func, int line)54{55pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id);56_dump_field("n1: ", n1, func, line);57_dump_field("n2: ", n2, func, line);58_dump_field("n3: ", n3, func, line);59_dump_field("n4: ", n4, func, line);60pr_devel("%s:%d: v1: %016llx\n", func, line, v1);61pr_devel("%s:%d: v2: %016llx\n", func, line, v2);62}6364/**65* make_first_field - Make the first field of a repository node name.66* @text: Text portion of the field.67* @index: Numeric index portion of the field. Use zero for 'don't care'.68*69* This routine sets the vendor id to zero (non-vendor specific).70* Returns field value.71*/7273static u64 make_first_field(const char *text, u64 index)74{75u64 n = 0;7677memcpy((char *)&n, text, strnlen(text, sizeof(n)));78return PS3_VENDOR_ID_NONE + (n >> 32) + index;79}8081/**82* make_field - Make subsequent fields of a repository node name.83* @text: Text portion of the field. Use "" for 'don't care'.84* @index: Numeric index portion of the field. Use zero for 'don't care'.85*86* Returns field value.87*/8889static u64 make_field(const char *text, u64 index)90{91u64 n = 0;9293memcpy((char *)&n, text, strnlen(text, sizeof(n)));94return n + index;95}9697/**98* read_node - Read a repository node from raw fields.99* @n1: First field of node name.100* @n2: Second field of node name. Use zero for 'don't care'.101* @n3: Third field of node name. Use zero for 'don't care'.102* @n4: Fourth field of node name. Use zero for 'don't care'.103* @v1: First repository value (high word).104* @v2: Second repository value (low word). Optional parameter, use zero105* for 'don't care'.106*/107108static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,109u64 *_v1, u64 *_v2)110{111int result;112u64 v1;113u64 v2;114115if (lpar_id == PS3_LPAR_ID_CURRENT) {116u64 id;117lv1_get_logical_partition_id(&id);118lpar_id = id;119}120121result = lv1_read_repository_node(lpar_id, n1, n2, n3, n4, &v1,122&v2);123124if (result) {125pr_warn("%s:%d: lv1_read_repository_node failed: %s\n",126__func__, __LINE__, ps3_result(result));127dump_node_name(lpar_id, n1, n2, n3, n4);128return -ENOENT;129}130131dump_node(lpar_id, n1, n2, n3, n4, v1, v2);132133if (_v1)134*_v1 = v1;135if (_v2)136*_v2 = v2;137138if (v1 && !_v1)139pr_devel("%s:%d: warning: discarding non-zero v1: %016llx\n",140__func__, __LINE__, v1);141if (v2 && !_v2)142pr_devel("%s:%d: warning: discarding non-zero v2: %016llx\n",143__func__, __LINE__, v2);144145return 0;146}147148int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,149u64 *value)150{151return read_node(PS3_LPAR_ID_PME,152make_first_field("bus", bus_index),153make_field(bus_str, 0),1540, 0,155value, NULL);156}157158int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id)159{160return read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index),161make_field("id", 0), 0, 0, bus_id, NULL);162}163164int ps3_repository_read_bus_type(unsigned int bus_index,165enum ps3_bus_type *bus_type)166{167int result;168u64 v1 = 0;169170result = read_node(PS3_LPAR_ID_PME,171make_first_field("bus", bus_index),172make_field("type", 0),1730, 0,174&v1, NULL);175*bus_type = v1;176return result;177}178179int ps3_repository_read_bus_num_dev(unsigned int bus_index,180unsigned int *num_dev)181{182int result;183u64 v1 = 0;184185result = read_node(PS3_LPAR_ID_PME,186make_first_field("bus", bus_index),187make_field("num_dev", 0),1880, 0,189&v1, NULL);190*num_dev = v1;191return result;192}193194int ps3_repository_read_dev_str(unsigned int bus_index,195unsigned int dev_index, const char *dev_str, u64 *value)196{197return read_node(PS3_LPAR_ID_PME,198make_first_field("bus", bus_index),199make_field("dev", dev_index),200make_field(dev_str, 0),2010,202value, NULL);203}204205int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,206u64 *dev_id)207{208return read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index),209make_field("dev", dev_index), make_field("id", 0), 0,210dev_id, NULL);211}212213int ps3_repository_read_dev_type(unsigned int bus_index,214unsigned int dev_index, enum ps3_dev_type *dev_type)215{216int result;217u64 v1 = 0;218219result = read_node(PS3_LPAR_ID_PME,220make_first_field("bus", bus_index),221make_field("dev", dev_index),222make_field("type", 0),2230,224&v1, NULL);225*dev_type = v1;226return result;227}228229int ps3_repository_read_dev_intr(unsigned int bus_index,230unsigned int dev_index, unsigned int intr_index,231enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id)232{233int result;234u64 v1 = 0;235u64 v2 = 0;236237result = read_node(PS3_LPAR_ID_PME,238make_first_field("bus", bus_index),239make_field("dev", dev_index),240make_field("intr", intr_index),2410,242&v1, &v2);243*intr_type = v1;244*interrupt_id = v2;245return result;246}247248int ps3_repository_read_dev_reg_type(unsigned int bus_index,249unsigned int dev_index, unsigned int reg_index,250enum ps3_reg_type *reg_type)251{252int result;253u64 v1 = 0;254255result = read_node(PS3_LPAR_ID_PME,256make_first_field("bus", bus_index),257make_field("dev", dev_index),258make_field("reg", reg_index),259make_field("type", 0),260&v1, NULL);261*reg_type = v1;262return result;263}264265int ps3_repository_read_dev_reg_addr(unsigned int bus_index,266unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len)267{268return read_node(PS3_LPAR_ID_PME,269make_first_field("bus", bus_index),270make_field("dev", dev_index),271make_field("reg", reg_index),272make_field("data", 0),273bus_addr, len);274}275276int ps3_repository_read_dev_reg(unsigned int bus_index,277unsigned int dev_index, unsigned int reg_index,278enum ps3_reg_type *reg_type, u64 *bus_addr, u64 *len)279{280int result = ps3_repository_read_dev_reg_type(bus_index, dev_index,281reg_index, reg_type);282return result ? result283: ps3_repository_read_dev_reg_addr(bus_index, dev_index,284reg_index, bus_addr, len);285}286287288289int ps3_repository_find_device(struct ps3_repository_device *repo)290{291int result;292struct ps3_repository_device tmp = *repo;293unsigned int num_dev;294295BUG_ON(repo->bus_index > 10);296BUG_ON(repo->dev_index > 10);297298result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);299300if (result) {301pr_devel("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);302return result;303}304305pr_devel("%s:%d: bus_type %u, bus_index %u, bus_id %llu, num_dev %u\n",306__func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,307num_dev);308309if (tmp.dev_index >= num_dev) {310pr_devel("%s:%d: no device found\n", __func__, __LINE__);311return -ENODEV;312}313314result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,315&tmp.dev_type);316317if (result) {318pr_devel("%s:%d read_dev_type failed\n", __func__, __LINE__);319return result;320}321322result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,323&tmp.dev_id);324325if (result) {326pr_devel("%s:%d ps3_repository_read_dev_id failed\n", __func__,327__LINE__);328return result;329}330331pr_devel("%s:%d: found: dev_type %u, dev_index %u, dev_id %llu\n",332__func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);333334*repo = tmp;335return 0;336}337338int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,339u64 bus_id, u64 dev_id)340{341int result = -ENODEV;342struct ps3_repository_device tmp;343unsigned int num_dev;344345pr_devel(" -> %s:%u: find device by id %llu:%llu\n", __func__, __LINE__,346bus_id, dev_id);347348for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) {349result = ps3_repository_read_bus_id(tmp.bus_index,350&tmp.bus_id);351if (result) {352pr_devel("%s:%u read_bus_id(%u) failed\n", __func__,353__LINE__, tmp.bus_index);354return result;355}356357if (tmp.bus_id == bus_id)358goto found_bus;359360pr_devel("%s:%u: skip, bus_id %llu\n", __func__, __LINE__,361tmp.bus_id);362}363pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__);364return result;365366found_bus:367result = ps3_repository_read_bus_type(tmp.bus_index, &tmp.bus_type);368if (result) {369pr_devel("%s:%u read_bus_type(%u) failed\n", __func__,370__LINE__, tmp.bus_index);371return result;372}373374result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);375if (result) {376pr_devel("%s:%u read_bus_num_dev failed\n", __func__,377__LINE__);378return result;379}380381for (tmp.dev_index = 0; tmp.dev_index < num_dev; tmp.dev_index++) {382result = ps3_repository_read_dev_id(tmp.bus_index,383tmp.dev_index,384&tmp.dev_id);385if (result) {386pr_devel("%s:%u read_dev_id(%u:%u) failed\n", __func__,387__LINE__, tmp.bus_index, tmp.dev_index);388return result;389}390391if (tmp.dev_id == dev_id)392goto found_dev;393394pr_devel("%s:%u: skip, dev_id %llu\n", __func__, __LINE__,395tmp.dev_id);396}397pr_devel(" <- %s:%u: dev not found\n", __func__, __LINE__);398return result;399400found_dev:401result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,402&tmp.dev_type);403if (result) {404pr_devel("%s:%u read_dev_type failed\n", __func__, __LINE__);405return result;406}407408pr_devel(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%llu:%llu)\n",409__func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index,410tmp.dev_index, tmp.bus_id, tmp.dev_id);411*repo = tmp;412return 0;413}414415int __init ps3_repository_find_devices(enum ps3_bus_type bus_type,416int (*callback)(const struct ps3_repository_device *repo))417{418int result = 0;419struct ps3_repository_device repo;420421pr_devel(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);422423repo.bus_type = bus_type;424result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);425if (result) {426pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__);427return result;428}429430result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);431if (result) {432pr_devel("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__,433repo.bus_index);434return result;435}436437for (repo.dev_index = 0; ; repo.dev_index++) {438result = ps3_repository_find_device(&repo);439if (result == -ENODEV) {440result = 0;441break;442} else if (result)443break;444445result = callback(&repo);446if (result) {447pr_devel("%s:%d: abort at callback\n", __func__,448__LINE__);449break;450}451}452453pr_devel(" <- %s:%d\n", __func__, __LINE__);454return result;455}456457int __init ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,458unsigned int *bus_index)459{460unsigned int i;461enum ps3_bus_type type;462int error;463464for (i = from; i < 10; i++) {465error = ps3_repository_read_bus_type(i, &type);466if (error) {467pr_devel("%s:%d read_bus_type failed\n",468__func__, __LINE__);469*bus_index = UINT_MAX;470return error;471}472if (type == bus_type) {473*bus_index = i;474return 0;475}476}477*bus_index = UINT_MAX;478return -ENODEV;479}480481int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,482enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)483{484int result = 0;485unsigned int res_index;486487pr_devel("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type);488489*interrupt_id = UINT_MAX;490491for (res_index = 0; res_index < 10; res_index++) {492enum ps3_interrupt_type t;493unsigned int id;494495result = ps3_repository_read_dev_intr(repo->bus_index,496repo->dev_index, res_index, &t, &id);497498if (result) {499pr_devel("%s:%d read_dev_intr failed\n",500__func__, __LINE__);501return result;502}503504if (t == intr_type) {505*interrupt_id = id;506break;507}508}509510if (res_index == 10)511return -ENODEV;512513pr_devel("%s:%d: found intr_type %u at res_index %u\n",514__func__, __LINE__, intr_type, res_index);515516return result;517}518519int ps3_repository_find_reg(const struct ps3_repository_device *repo,520enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len)521{522int result = 0;523unsigned int res_index;524525pr_devel("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type);526527*bus_addr = *len = 0;528529for (res_index = 0; res_index < 10; res_index++) {530enum ps3_reg_type t;531u64 a;532u64 l;533534result = ps3_repository_read_dev_reg(repo->bus_index,535repo->dev_index, res_index, &t, &a, &l);536537if (result) {538pr_devel("%s:%d read_dev_reg failed\n",539__func__, __LINE__);540return result;541}542543if (t == reg_type) {544*bus_addr = a;545*len = l;546break;547}548}549550if (res_index == 10)551return -ENODEV;552553pr_devel("%s:%d: found reg_type %u at res_index %u\n",554__func__, __LINE__, reg_type, res_index);555556return result;557}558559int ps3_repository_read_stor_dev_port(unsigned int bus_index,560unsigned int dev_index, u64 *port)561{562return read_node(PS3_LPAR_ID_PME,563make_first_field("bus", bus_index),564make_field("dev", dev_index),565make_field("port", 0),5660, port, NULL);567}568569int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index,570unsigned int dev_index, u64 *blk_size)571{572return read_node(PS3_LPAR_ID_PME,573make_first_field("bus", bus_index),574make_field("dev", dev_index),575make_field("blk_size", 0),5760, blk_size, NULL);577}578579int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index,580unsigned int dev_index, u64 *num_blocks)581{582return read_node(PS3_LPAR_ID_PME,583make_first_field("bus", bus_index),584make_field("dev", dev_index),585make_field("n_blocks", 0),5860, num_blocks, NULL);587}588589int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index,590unsigned int dev_index, unsigned int *num_regions)591{592int result;593u64 v1 = 0;594595result = read_node(PS3_LPAR_ID_PME,596make_first_field("bus", bus_index),597make_field("dev", dev_index),598make_field("n_regs", 0),5990, &v1, NULL);600*num_regions = v1;601return result;602}603604int ps3_repository_read_stor_dev_region_id(unsigned int bus_index,605unsigned int dev_index, unsigned int region_index,606unsigned int *region_id)607{608int result;609u64 v1 = 0;610611result = read_node(PS3_LPAR_ID_PME,612make_first_field("bus", bus_index),613make_field("dev", dev_index),614make_field("region", region_index),615make_field("id", 0),616&v1, NULL);617*region_id = v1;618return result;619}620621int ps3_repository_read_stor_dev_region_size(unsigned int bus_index,622unsigned int dev_index, unsigned int region_index, u64 *region_size)623{624return read_node(PS3_LPAR_ID_PME,625make_first_field("bus", bus_index),626make_field("dev", dev_index),627make_field("region", region_index),628make_field("size", 0),629region_size, NULL);630}631632int ps3_repository_read_stor_dev_region_start(unsigned int bus_index,633unsigned int dev_index, unsigned int region_index, u64 *region_start)634{635return read_node(PS3_LPAR_ID_PME,636make_first_field("bus", bus_index),637make_field("dev", dev_index),638make_field("region", region_index),639make_field("start", 0),640region_start, NULL);641}642643int ps3_repository_read_stor_dev_info(unsigned int bus_index,644unsigned int dev_index, u64 *port, u64 *blk_size,645u64 *num_blocks, unsigned int *num_regions)646{647int result;648649result = ps3_repository_read_stor_dev_port(bus_index, dev_index, port);650if (result)651return result;652653result = ps3_repository_read_stor_dev_blk_size(bus_index, dev_index,654blk_size);655if (result)656return result;657658result = ps3_repository_read_stor_dev_num_blocks(bus_index, dev_index,659num_blocks);660if (result)661return result;662663result = ps3_repository_read_stor_dev_num_regions(bus_index, dev_index,664num_regions);665return result;666}667668int ps3_repository_read_stor_dev_region(unsigned int bus_index,669unsigned int dev_index, unsigned int region_index,670unsigned int *region_id, u64 *region_start, u64 *region_size)671{672int result;673674result = ps3_repository_read_stor_dev_region_id(bus_index, dev_index,675region_index, region_id);676if (result)677return result;678679result = ps3_repository_read_stor_dev_region_start(bus_index, dev_index,680region_index, region_start);681if (result)682return result;683684result = ps3_repository_read_stor_dev_region_size(bus_index, dev_index,685region_index, region_size);686return result;687}688689/**690* ps3_repository_read_num_pu - Number of logical PU processors for this lpar.691*/692693int ps3_repository_read_num_pu(u64 *num_pu)694{695*num_pu = 0;696return read_node(PS3_LPAR_ID_CURRENT,697make_first_field("bi", 0),698make_field("pun", 0),6990, 0,700num_pu, NULL);701}702703/**704* ps3_repository_read_pu_id - Read the logical PU id.705* @pu_index: Zero based index.706* @pu_id: The logical PU id.707*/708709int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id)710{711return read_node(PS3_LPAR_ID_CURRENT,712make_first_field("bi", 0),713make_field("pu", pu_index),7140, 0,715pu_id, NULL);716}717718int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size)719{720return read_node(PS3_LPAR_ID_CURRENT,721make_first_field("bi", 0),722make_field("pu", 0),723ppe_id,724make_field("rm_size", 0),725rm_size, NULL);726}727728int ps3_repository_read_region_total(u64 *region_total)729{730return read_node(PS3_LPAR_ID_CURRENT,731make_first_field("bi", 0),732make_field("rgntotal", 0),7330, 0,734region_total, NULL);735}736737/**738* ps3_repository_read_mm_info - Read mm info for single pu system.739* @rm_base: Real mode memory base address.740* @rm_size: Real mode memory size.741* @region_total: Maximum memory region size.742*/743744int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)745{746int result;747u64 ppe_id;748749lv1_get_logical_ppe_id(&ppe_id);750*rm_base = 0;751result = ps3_repository_read_rm_size(ppe_id, rm_size);752return result ? result753: ps3_repository_read_region_total(region_total);754}755756/**757* ps3_repository_read_highmem_region_count - Read the number of highmem regions758*759* Bootloaders must arrange the repository nodes such that regions are indexed760* with a region_index from 0 to region_count-1.761*/762763int ps3_repository_read_highmem_region_count(unsigned int *region_count)764{765int result;766u64 v1 = 0;767768result = read_node(PS3_LPAR_ID_CURRENT,769make_first_field("highmem", 0),770make_field("region", 0),771make_field("count", 0),7720,773&v1, NULL);774*region_count = v1;775return result;776}777778779int ps3_repository_read_highmem_base(unsigned int region_index,780u64 *highmem_base)781{782return read_node(PS3_LPAR_ID_CURRENT,783make_first_field("highmem", 0),784make_field("region", region_index),785make_field("base", 0),7860,787highmem_base, NULL);788}789790int ps3_repository_read_highmem_size(unsigned int region_index,791u64 *highmem_size)792{793return read_node(PS3_LPAR_ID_CURRENT,794make_first_field("highmem", 0),795make_field("region", region_index),796make_field("size", 0),7970,798highmem_size, NULL);799}800801/**802* ps3_repository_read_highmem_info - Read high memory region info803* @region_index: Region index, {0,..,region_count-1}.804* @highmem_base: High memory base address.805* @highmem_size: High memory size.806*807* Bootloaders that preallocate highmem regions must place the808* region info into the repository at these well known nodes.809*/810811int ps3_repository_read_highmem_info(unsigned int region_index,812u64 *highmem_base, u64 *highmem_size)813{814int result;815816*highmem_base = 0;817result = ps3_repository_read_highmem_base(region_index, highmem_base);818return result ? result819: ps3_repository_read_highmem_size(region_index, highmem_size);820}821822/**823* ps3_repository_read_num_spu_reserved - Number of physical spus reserved.824* @num_spu: Number of physical spus.825*/826827int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)828{829int result;830u64 v1 = 0;831832result = read_node(PS3_LPAR_ID_CURRENT,833make_first_field("bi", 0),834make_field("spun", 0),8350, 0,836&v1, NULL);837*num_spu_reserved = v1;838return result;839}840841/**842* ps3_repository_read_num_spu_resource_id - Number of spu resource reservations.843* @num_resource_id: Number of spu resource ids.844*/845846int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)847{848int result;849u64 v1 = 0;850851result = read_node(PS3_LPAR_ID_CURRENT,852make_first_field("bi", 0),853make_field("spursvn", 0),8540, 0,855&v1, NULL);856*num_resource_id = v1;857return result;858}859860/**861* ps3_repository_read_spu_resource_id - spu resource reservation id value.862* @res_index: Resource reservation index.863* @resource_type: Resource reservation type.864* @resource_id: Resource reservation id.865*/866867int ps3_repository_read_spu_resource_id(unsigned int res_index,868enum ps3_spu_resource_type *resource_type, unsigned int *resource_id)869{870int result;871u64 v1 = 0;872u64 v2 = 0;873874result = read_node(PS3_LPAR_ID_CURRENT,875make_first_field("bi", 0),876make_field("spursv", 0),877res_index,8780,879&v1, &v2);880*resource_type = v1;881*resource_id = v2;882return result;883}884885static int ps3_repository_read_boot_dat_address(u64 *address)886{887return read_node(PS3_LPAR_ID_CURRENT,888make_first_field("bi", 0),889make_field("boot_dat", 0),890make_field("address", 0),8910,892address, NULL);893}894895int ps3_repository_read_boot_dat_size(unsigned int *size)896{897int result;898u64 v1 = 0;899900result = read_node(PS3_LPAR_ID_CURRENT,901make_first_field("bi", 0),902make_field("boot_dat", 0),903make_field("size", 0),9040,905&v1, NULL);906*size = v1;907return result;908}909910int __init ps3_repository_read_vuart_av_port(unsigned int *port)911{912int result;913u64 v1 = 0;914915result = read_node(PS3_LPAR_ID_CURRENT,916make_first_field("bi", 0),917make_field("vir_uart", 0),918make_field("port", 0),919make_field("avset", 0),920&v1, NULL);921*port = v1;922return result;923}924925int __init ps3_repository_read_vuart_sysmgr_port(unsigned int *port)926{927int result;928u64 v1 = 0;929930result = read_node(PS3_LPAR_ID_CURRENT,931make_first_field("bi", 0),932make_field("vir_uart", 0),933make_field("port", 0),934make_field("sysmgr", 0),935&v1, NULL);936*port = v1;937return result;938}939940/**941* ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.942* @lpar_addr: lpar address of cell_ext_os_area943* @size: size of cell_ext_os_area944*/945946int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size)947{948int result;949950*size = 0;951result = ps3_repository_read_boot_dat_address(lpar_addr);952return result ? result953: ps3_repository_read_boot_dat_size(size);954}955956/**957* ps3_repository_read_num_be - Number of physical BE processors in the system.958*/959960int ps3_repository_read_num_be(unsigned int *num_be)961{962int result;963u64 v1 = 0;964965result = read_node(PS3_LPAR_ID_PME,966make_first_field("ben", 0),9670,9680,9690,970&v1, NULL);971*num_be = v1;972return result;973}974975/**976* ps3_repository_read_be_node_id - Read the physical BE processor node id.977* @be_index: Zero based index.978* @node_id: The BE processor node id.979*/980981int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id)982{983return read_node(PS3_LPAR_ID_PME,984make_first_field("be", be_index),9850,9860,9870,988node_id, NULL);989}990991/**992* ps3_repository_read_be_id - Read the physical BE processor id.993* @node_id: The BE processor node id.994* @be_id: The BE processor id.995*/996997int ps3_repository_read_be_id(u64 node_id, u64 *be_id)998{999return read_node(PS3_LPAR_ID_PME,1000make_first_field("be", 0),1001node_id,10020,10030,1004be_id, NULL);1005}10061007int __init ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq)1008{1009return read_node(PS3_LPAR_ID_PME,1010make_first_field("be", 0),1011node_id,1012make_field("clock", 0),10130,1014tb_freq, NULL);1015}10161017int __init ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq)1018{1019int result;1020u64 node_id;10211022*tb_freq = 0;1023result = ps3_repository_read_be_node_id(be_index, &node_id);1024return result ? result1025: ps3_repository_read_tb_freq(node_id, tb_freq);1026}10271028int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar,1029u64 *rights)1030{1031int result;1032u64 node_id;10331034*lpar = 0;1035*rights = 0;1036result = ps3_repository_read_be_node_id(be_index, &node_id);1037return result ? result1038: read_node(PS3_LPAR_ID_PME,1039make_first_field("be", 0),1040node_id,1041make_field("lpm", 0),1042make_field("priv", 0),1043lpar, rights);1044}10451046#if defined(CONFIG_PS3_REPOSITORY_WRITE)10471048static int create_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2)1049{1050int result;10511052dump_node(0, n1, n2, n3, n4, v1, v2);10531054result = lv1_create_repository_node(n1, n2, n3, n4, v1, v2);10551056if (result) {1057pr_devel("%s:%d: lv1_create_repository_node failed: %s\n",1058__func__, __LINE__, ps3_result(result));1059return -ENOENT;1060}10611062return 0;1063}10641065static int delete_node(u64 n1, u64 n2, u64 n3, u64 n4)1066{1067int result;10681069dump_node(0, n1, n2, n3, n4, 0, 0);10701071result = lv1_delete_repository_node(n1, n2, n3, n4);10721073if (result) {1074pr_devel("%s:%d: lv1_delete_repository_node failed: %s\n",1075__func__, __LINE__, ps3_result(result));1076return -ENOENT;1077}10781079return 0;1080}10811082static int write_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2)1083{1084int result;10851086result = create_node(n1, n2, n3, n4, v1, v2);10871088if (!result)1089return 0;10901091result = lv1_write_repository_node(n1, n2, n3, n4, v1, v2);10921093if (result) {1094pr_devel("%s:%d: lv1_write_repository_node failed: %s\n",1095__func__, __LINE__, ps3_result(result));1096return -ENOENT;1097}10981099return 0;1100}11011102int ps3_repository_write_highmem_region_count(unsigned int region_count)1103{1104int result;1105u64 v1 = (u64)region_count;11061107result = write_node(1108make_first_field("highmem", 0),1109make_field("region", 0),1110make_field("count", 0),11110,1112v1, 0);1113return result;1114}11151116int ps3_repository_write_highmem_base(unsigned int region_index,1117u64 highmem_base)1118{1119return write_node(1120make_first_field("highmem", 0),1121make_field("region", region_index),1122make_field("base", 0),11230,1124highmem_base, 0);1125}11261127int ps3_repository_write_highmem_size(unsigned int region_index,1128u64 highmem_size)1129{1130return write_node(1131make_first_field("highmem", 0),1132make_field("region", region_index),1133make_field("size", 0),11340,1135highmem_size, 0);1136}11371138int ps3_repository_write_highmem_info(unsigned int region_index,1139u64 highmem_base, u64 highmem_size)1140{1141int result;11421143result = ps3_repository_write_highmem_base(region_index, highmem_base);1144return result ? result1145: ps3_repository_write_highmem_size(region_index, highmem_size);1146}11471148static int ps3_repository_delete_highmem_base(unsigned int region_index)1149{1150return delete_node(1151make_first_field("highmem", 0),1152make_field("region", region_index),1153make_field("base", 0),11540);1155}11561157static int ps3_repository_delete_highmem_size(unsigned int region_index)1158{1159return delete_node(1160make_first_field("highmem", 0),1161make_field("region", region_index),1162make_field("size", 0),11630);1164}11651166int ps3_repository_delete_highmem_info(unsigned int region_index)1167{1168int result;11691170result = ps3_repository_delete_highmem_base(region_index);1171result += ps3_repository_delete_highmem_size(region_index);11721173return result ? -1 : 0;1174}11751176#endif /* defined(CONFIG_PS3_REPOSITORY_WRITE) */11771178#if defined(DEBUG)11791180int __init ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)1181{1182int result = 0;1183unsigned int res_index;11841185pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,1186repo->bus_index, repo->dev_index);11871188for (res_index = 0; res_index < 10; res_index++) {1189enum ps3_interrupt_type intr_type;1190unsigned int interrupt_id;11911192result = ps3_repository_read_dev_intr(repo->bus_index,1193repo->dev_index, res_index, &intr_type, &interrupt_id);11941195if (result) {1196if (result != LV1_NO_ENTRY)1197pr_devel("%s:%d ps3_repository_read_dev_intr"1198" (%u:%u) failed\n", __func__, __LINE__,1199repo->bus_index, repo->dev_index);1200break;1201}12021203pr_devel("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",1204__func__, __LINE__, repo->bus_index, repo->dev_index,1205intr_type, interrupt_id);1206}12071208for (res_index = 0; res_index < 10; res_index++) {1209enum ps3_reg_type reg_type;1210u64 bus_addr;1211u64 len;12121213result = ps3_repository_read_dev_reg(repo->bus_index,1214repo->dev_index, res_index, ®_type, &bus_addr, &len);12151216if (result) {1217if (result != LV1_NO_ENTRY)1218pr_devel("%s:%d ps3_repository_read_dev_reg"1219" (%u:%u) failed\n", __func__, __LINE__,1220repo->bus_index, repo->dev_index);1221break;1222}12231224pr_devel("%s:%d (%u:%u) reg_type %u, bus_addr %llxh, len %llxh\n",1225__func__, __LINE__, repo->bus_index, repo->dev_index,1226reg_type, bus_addr, len);1227}12281229pr_devel(" <- %s:%d\n", __func__, __LINE__);1230return result;1231}12321233static int __init dump_stor_dev_info(struct ps3_repository_device *repo)1234{1235int result = 0;1236unsigned int num_regions, region_index;1237u64 port, blk_size, num_blocks;12381239pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,1240repo->bus_index, repo->dev_index);12411242result = ps3_repository_read_stor_dev_info(repo->bus_index,1243repo->dev_index, &port, &blk_size, &num_blocks, &num_regions);1244if (result) {1245pr_devel("%s:%d ps3_repository_read_stor_dev_info"1246" (%u:%u) failed\n", __func__, __LINE__,1247repo->bus_index, repo->dev_index);1248goto out;1249}12501251pr_devel("%s:%d (%u:%u): port %llu, blk_size %llu, num_blocks "1252"%llu, num_regions %u\n",1253__func__, __LINE__, repo->bus_index, repo->dev_index,1254port, blk_size, num_blocks, num_regions);12551256for (region_index = 0; region_index < num_regions; region_index++) {1257unsigned int region_id;1258u64 region_start, region_size;12591260result = ps3_repository_read_stor_dev_region(repo->bus_index,1261repo->dev_index, region_index, ®ion_id,1262®ion_start, ®ion_size);1263if (result) {1264pr_devel("%s:%d ps3_repository_read_stor_dev_region"1265" (%u:%u) failed\n", __func__, __LINE__,1266repo->bus_index, repo->dev_index);1267break;1268}12691270pr_devel("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",1271__func__, __LINE__, repo->bus_index, repo->dev_index,1272region_id, (unsigned long)region_start,1273(unsigned long)region_size);1274}12751276out:1277pr_devel(" <- %s:%d\n", __func__, __LINE__);1278return result;1279}12801281static int __init dump_device_info(struct ps3_repository_device *repo,1282unsigned int num_dev)1283{1284int result = 0;12851286pr_devel(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index);12871288for (repo->dev_index = 0; repo->dev_index < num_dev;1289repo->dev_index++) {12901291result = ps3_repository_read_dev_type(repo->bus_index,1292repo->dev_index, &repo->dev_type);12931294if (result) {1295pr_devel("%s:%d ps3_repository_read_dev_type"1296" (%u:%u) failed\n", __func__, __LINE__,1297repo->bus_index, repo->dev_index);1298break;1299}13001301result = ps3_repository_read_dev_id(repo->bus_index,1302repo->dev_index, &repo->dev_id);13031304if (result) {1305pr_devel("%s:%d ps3_repository_read_dev_id"1306" (%u:%u) failed\n", __func__, __LINE__,1307repo->bus_index, repo->dev_index);1308continue;1309}13101311pr_devel("%s:%d (%u:%u): dev_type %u, dev_id %lu\n", __func__,1312__LINE__, repo->bus_index, repo->dev_index,1313repo->dev_type, (unsigned long)repo->dev_id);13141315ps3_repository_dump_resource_info(repo);13161317if (repo->bus_type == PS3_BUS_TYPE_STORAGE)1318dump_stor_dev_info(repo);1319}13201321pr_devel(" <- %s:%d\n", __func__, __LINE__);1322return result;1323}13241325int __init ps3_repository_dump_bus_info(void)1326{1327int result = 0;1328struct ps3_repository_device repo;13291330pr_devel(" -> %s:%d\n", __func__, __LINE__);13311332memset(&repo, 0, sizeof(repo));13331334for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {1335unsigned int num_dev;13361337result = ps3_repository_read_bus_type(repo.bus_index,1338&repo.bus_type);13391340if (result) {1341pr_devel("%s:%d read_bus_type(%u) failed\n",1342__func__, __LINE__, repo.bus_index);1343break;1344}13451346result = ps3_repository_read_bus_id(repo.bus_index,1347&repo.bus_id);13481349if (result) {1350pr_devel("%s:%d read_bus_id(%u) failed\n",1351__func__, __LINE__, repo.bus_index);1352continue;1353}13541355if (repo.bus_index != repo.bus_id)1356pr_devel("%s:%d bus_index != bus_id\n",1357__func__, __LINE__);13581359result = ps3_repository_read_bus_num_dev(repo.bus_index,1360&num_dev);13611362if (result) {1363pr_devel("%s:%d read_bus_num_dev(%u) failed\n",1364__func__, __LINE__, repo.bus_index);1365continue;1366}13671368pr_devel("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n",1369__func__, __LINE__, repo.bus_index, repo.bus_type,1370(unsigned long)repo.bus_id, num_dev);13711372dump_device_info(&repo, num_dev);1373}13741375pr_devel(" <- %s:%d\n", __func__, __LINE__);1376return result;1377}13781379#endif /* defined(DEBUG) */138013811382