18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * drmem.h: Power specific logical memory block representation 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2017 IBM Corporation 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_LMB_H 98c2ecf20Sopenharmony_ci#define _ASM_POWERPC_LMB_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/sched.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cistruct drmem_lmb { 148c2ecf20Sopenharmony_ci u64 base_addr; 158c2ecf20Sopenharmony_ci u32 drc_index; 168c2ecf20Sopenharmony_ci u32 aa_index; 178c2ecf20Sopenharmony_ci u32 flags; 188c2ecf20Sopenharmony_ci}; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistruct drmem_lmb_info { 218c2ecf20Sopenharmony_ci struct drmem_lmb *lmbs; 228c2ecf20Sopenharmony_ci int n_lmbs; 238c2ecf20Sopenharmony_ci u64 lmb_size; 248c2ecf20Sopenharmony_ci}; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ciextern struct drmem_lmb_info *drmem_info; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic inline struct drmem_lmb *drmem_lmb_next(struct drmem_lmb *lmb, 298c2ecf20Sopenharmony_ci const struct drmem_lmb *start) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci /* 328c2ecf20Sopenharmony_ci * DLPAR code paths can take several milliseconds per element 338c2ecf20Sopenharmony_ci * when interacting with firmware. Ensure that we don't 348c2ecf20Sopenharmony_ci * unfairly monopolize the CPU. 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_ci if (((++lmb - start) % 16) == 0) 378c2ecf20Sopenharmony_ci cond_resched(); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci return lmb; 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define for_each_drmem_lmb_in_range(lmb, start, end) \ 438c2ecf20Sopenharmony_ci for ((lmb) = (start); (lmb) < (end); lmb = drmem_lmb_next(lmb, start)) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define for_each_drmem_lmb(lmb) \ 468c2ecf20Sopenharmony_ci for_each_drmem_lmb_in_range((lmb), \ 478c2ecf20Sopenharmony_ci &drmem_info->lmbs[0], \ 488c2ecf20Sopenharmony_ci &drmem_info->lmbs[drmem_info->n_lmbs]) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* 518c2ecf20Sopenharmony_ci * The of_drconf_cell_v1 struct defines the layout of the LMB data 528c2ecf20Sopenharmony_ci * specified in the ibm,dynamic-memory device tree property. 538c2ecf20Sopenharmony_ci * The property itself is a 32-bit value specifying the number of 548c2ecf20Sopenharmony_ci * LMBs followed by an array of of_drconf_cell_v1 entries, one 558c2ecf20Sopenharmony_ci * per LMB. 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_cistruct of_drconf_cell_v1 { 588c2ecf20Sopenharmony_ci __be64 base_addr; 598c2ecf20Sopenharmony_ci __be32 drc_index; 608c2ecf20Sopenharmony_ci __be32 reserved; 618c2ecf20Sopenharmony_ci __be32 aa_index; 628c2ecf20Sopenharmony_ci __be32 flags; 638c2ecf20Sopenharmony_ci}; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci/* 668c2ecf20Sopenharmony_ci * Version 2 of the ibm,dynamic-memory property is defined as a 678c2ecf20Sopenharmony_ci * 32-bit value specifying the number of LMB sets followed by an 688c2ecf20Sopenharmony_ci * array of of_drconf_cell_v2 entries, one per LMB set. 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_cistruct of_drconf_cell_v2 { 718c2ecf20Sopenharmony_ci u32 seq_lmbs; 728c2ecf20Sopenharmony_ci u64 base_addr; 738c2ecf20Sopenharmony_ci u32 drc_index; 748c2ecf20Sopenharmony_ci u32 aa_index; 758c2ecf20Sopenharmony_ci u32 flags; 768c2ecf20Sopenharmony_ci} __packed; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#define DRCONF_MEM_ASSIGNED 0x00000008 798c2ecf20Sopenharmony_ci#define DRCONF_MEM_AI_INVALID 0x00000040 808c2ecf20Sopenharmony_ci#define DRCONF_MEM_RESERVED 0x00000080 818c2ecf20Sopenharmony_ci#define DRCONF_MEM_HOTREMOVABLE 0x00000100 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic inline u64 drmem_lmb_size(void) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci return drmem_info->lmb_size; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#define DRMEM_LMB_RESERVED 0x80000000 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic inline void drmem_mark_lmb_reserved(struct drmem_lmb *lmb) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci lmb->flags |= DRMEM_LMB_RESERVED; 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic inline void drmem_remove_lmb_reservation(struct drmem_lmb *lmb) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci lmb->flags &= ~DRMEM_LMB_RESERVED; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic inline bool drmem_lmb_reserved(struct drmem_lmb *lmb) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci return lmb->flags & DRMEM_LMB_RESERVED; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ciu64 drmem_lmb_memory_max(void); 1068c2ecf20Sopenharmony_ciint walk_drmem_lmbs(struct device_node *dn, void *data, 1078c2ecf20Sopenharmony_ci int (*func)(struct drmem_lmb *, const __be32 **, void *)); 1088c2ecf20Sopenharmony_ciint drmem_update_dt(void); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_PSERIES 1118c2ecf20Sopenharmony_ciint __init 1128c2ecf20Sopenharmony_ciwalk_drmem_lmbs_early(unsigned long node, void *data, 1138c2ecf20Sopenharmony_ci int (*func)(struct drmem_lmb *, const __be32 **, void *)); 1148c2ecf20Sopenharmony_ci#endif 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic inline void invalidate_lmb_associativity_index(struct drmem_lmb *lmb) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci lmb->aa_index = 0xffffffff; 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci#endif /* _ASM_POWERPC_LMB_H */ 122