162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * drmem.h: Power specific logical memory block representation 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2017 IBM Corporation 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#ifndef _ASM_POWERPC_LMB_H 962306a36Sopenharmony_ci#define _ASM_POWERPC_LMB_H 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/sched.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistruct drmem_lmb { 1462306a36Sopenharmony_ci u64 base_addr; 1562306a36Sopenharmony_ci u32 drc_index; 1662306a36Sopenharmony_ci u32 aa_index; 1762306a36Sopenharmony_ci u32 flags; 1862306a36Sopenharmony_ci}; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistruct drmem_lmb_info { 2162306a36Sopenharmony_ci struct drmem_lmb *lmbs; 2262306a36Sopenharmony_ci int n_lmbs; 2362306a36Sopenharmony_ci u64 lmb_size; 2462306a36Sopenharmony_ci}; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistruct device_node; 2762306a36Sopenharmony_cistruct property; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ciextern struct drmem_lmb_info *drmem_info; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic inline struct drmem_lmb *drmem_lmb_next(struct drmem_lmb *lmb, 3262306a36Sopenharmony_ci const struct drmem_lmb *start) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci /* 3562306a36Sopenharmony_ci * DLPAR code paths can take several milliseconds per element 3662306a36Sopenharmony_ci * when interacting with firmware. Ensure that we don't 3762306a36Sopenharmony_ci * unfairly monopolize the CPU. 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci if (((++lmb - start) % 16) == 0) 4062306a36Sopenharmony_ci cond_resched(); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci return lmb; 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define for_each_drmem_lmb_in_range(lmb, start, end) \ 4662306a36Sopenharmony_ci for ((lmb) = (start); (lmb) < (end); lmb = drmem_lmb_next(lmb, start)) 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#define for_each_drmem_lmb(lmb) \ 4962306a36Sopenharmony_ci for_each_drmem_lmb_in_range((lmb), \ 5062306a36Sopenharmony_ci &drmem_info->lmbs[0], \ 5162306a36Sopenharmony_ci &drmem_info->lmbs[drmem_info->n_lmbs]) 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* 5462306a36Sopenharmony_ci * The of_drconf_cell_v1 struct defines the layout of the LMB data 5562306a36Sopenharmony_ci * specified in the ibm,dynamic-memory device tree property. 5662306a36Sopenharmony_ci * The property itself is a 32-bit value specifying the number of 5762306a36Sopenharmony_ci * LMBs followed by an array of of_drconf_cell_v1 entries, one 5862306a36Sopenharmony_ci * per LMB. 5962306a36Sopenharmony_ci */ 6062306a36Sopenharmony_cistruct of_drconf_cell_v1 { 6162306a36Sopenharmony_ci __be64 base_addr; 6262306a36Sopenharmony_ci __be32 drc_index; 6362306a36Sopenharmony_ci __be32 reserved; 6462306a36Sopenharmony_ci __be32 aa_index; 6562306a36Sopenharmony_ci __be32 flags; 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* 6962306a36Sopenharmony_ci * Version 2 of the ibm,dynamic-memory property is defined as a 7062306a36Sopenharmony_ci * 32-bit value specifying the number of LMB sets followed by an 7162306a36Sopenharmony_ci * array of of_drconf_cell_v2 entries, one per LMB set. 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_cistruct of_drconf_cell_v2 { 7462306a36Sopenharmony_ci u32 seq_lmbs; 7562306a36Sopenharmony_ci u64 base_addr; 7662306a36Sopenharmony_ci u32 drc_index; 7762306a36Sopenharmony_ci u32 aa_index; 7862306a36Sopenharmony_ci u32 flags; 7962306a36Sopenharmony_ci} __packed; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci#define DRCONF_MEM_ASSIGNED 0x00000008 8262306a36Sopenharmony_ci#define DRCONF_MEM_AI_INVALID 0x00000040 8362306a36Sopenharmony_ci#define DRCONF_MEM_RESERVED 0x00000080 8462306a36Sopenharmony_ci#define DRCONF_MEM_HOTREMOVABLE 0x00000100 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic inline u64 drmem_lmb_size(void) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci return drmem_info->lmb_size; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci#define DRMEM_LMB_RESERVED 0x80000000 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic inline void drmem_mark_lmb_reserved(struct drmem_lmb *lmb) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci lmb->flags |= DRMEM_LMB_RESERVED; 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic inline void drmem_remove_lmb_reservation(struct drmem_lmb *lmb) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci lmb->flags &= ~DRMEM_LMB_RESERVED; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic inline bool drmem_lmb_reserved(struct drmem_lmb *lmb) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci return lmb->flags & DRMEM_LMB_RESERVED; 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ciu64 drmem_lmb_memory_max(void); 10962306a36Sopenharmony_ciint walk_drmem_lmbs(struct device_node *dn, void *data, 11062306a36Sopenharmony_ci int (*func)(struct drmem_lmb *, const __be32 **, void *)); 11162306a36Sopenharmony_ciint drmem_update_dt(void); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#ifdef CONFIG_PPC_PSERIES 11462306a36Sopenharmony_ciint __init 11562306a36Sopenharmony_ciwalk_drmem_lmbs_early(unsigned long node, void *data, 11662306a36Sopenharmony_ci int (*func)(struct drmem_lmb *, const __be32 **, void *)); 11762306a36Sopenharmony_civoid drmem_update_lmbs(struct property *prop); 11862306a36Sopenharmony_ci#endif 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic inline void invalidate_lmb_associativity_index(struct drmem_lmb *lmb) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci lmb->aa_index = 0xffffffff; 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#endif /* _ASM_POWERPC_LMB_H */ 126