STRUCT IP30_HEART_REGS(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’– NAME πŸ’–

okay so welcome to the struct ip30_heart_regs(9) page from the Kernel API Manual, bestie ✨ β€” this is literally the struct that maps IP30 HEART registers πŸ’…


✨ SYNOPSIS ✨

no cap, here’s the whole struct exactly as it is, every field in its little lane 🫢

       struct ip30_heart_regs {
           u64 mode;
           u64 sdram_mode;
           u64 mem_refresh;
           u64 mem_req_arb;
           union {
             u64 q[HEART_MEMORY_BANKS];
             u32 l[HEART_MEMORY_BANKS * 2];
           } mem_cfg;
           u64 fc_mode;
           u64 fc_timer_limit;
           u64 fc_addr[2];
           u64 fc_credit_cnt[2];
           u64 fc_timer[2];
           u64 status;
           u64 bus_err_addr;
           u64 bus_err_misc;
           u64 mem_err_addr;
           u64 mem_err_data;
           u64 piur_acc_err;
           u64 mlan_clock_div;
           u64 mlan_ctrl;
           u64 __pad0[0x01e8];
           u64 undefined;
           u64 __pad1[0x1dff];
           u64 imr[HEART_MAX_CPUS];
           u64 set_isr;
           u64 clear_isr;
           u64 isr;
           u64 imsr;
           u64 cause;
           u64 __pad2[0x1ff7];
           u64 count;
           u64 __pad3[0x1fff];
           u64 compare;
           u64 __pad4[0x1fff];
           u64 trigger;
           u64 __pad5[0x1fff];
           u64 cpuid;
           u64 __pad6[0x1fff];
           u64 sync;
        };

🫢 Members 🫢

okay bestie, every single member, in order, with the lore πŸ‘‘:

  • mode β€” maps to HEART_MODE; Purpose Unknown, but machine reset gets called from here πŸ‘€
  • sdram_mode β€” maps to HEART_SDRAM_MODE; purpose unknown πŸ¦‹
  • mem_refresh β€” maps to HEART_MEM_REF; purpose unknown 🌸
  • mem_req_arb β€” maps to HEART_MEM_REQ_ARB; purpose unknown πŸŽ€
  • mem_cfg.q β€” union for 64bit access to HEART_MEMCFG β€” 4x 64bit registers πŸ’…
  • mem_cfg.l β€” union for 32bit access to HEART_MEMCFG β€” 8x 32bit registers πŸ’…
  • fc_mode β€” maps to HEART_FC_MODE; Purpose Unknown, possibly for GFX flow control πŸŒ€
  • fc_timer_limit β€” maps to HEART_FC_TIMER_LIMIT; purpose unknown ⏳
  • fc_addr β€” maps to HEART_FC0_ADDR, HEART_FC1_ADDR; purpose unknown πŸ“
  • fc_credit_cnt β€” maps to HEART_FC0_CR_CNT, HEART_FC1_CR_CNT; purpose unknown πŸͺ™
  • fc_timer β€” maps to HEART_FC0_TIMER, HEART_FC1_TIMER; purpose unknown βŒ›
  • status β€” maps to HEART_STATUS; HEART status information πŸ’–
  • bus_err_addr β€” maps to HEART_BERR_ADDR; likely contains addr of recent SIGBUS 😭
  • bus_err_misc β€” maps to HEART_BERR_MISC; purpose unknown πŸ™ˆ
  • mem_err_addr β€” maps to HEART_MEMERR_ADDR; likely contains addr of recent mem err πŸ’€
  • mem_err_data β€” maps to HEART_MEMERR_DATA; purpose unknown πŸ“
  • piur_acc_err β€” maps to HEART_PIUR_ACC_ERR; likely for access err to HEART regs 🚨
  • mlan_clock_div β€” maps to HEART_MLAN_CLK_DIV; MicroLAN clock divider πŸ•°οΈ
  • mlan_ctrl β€” maps to HEART_MLAN_CTL; MicroLAN control πŸŽ›οΈ
  • __pad0 β€” 0x0f40 bytes of padding -> next HEART register 0x01000 🧚
  • undefined β€” Undefined/diag register, write to it triggers PIUR_ACC_ERR ⚠️
  • __pad1 β€” 0xeff8 bytes of padding -> next HEART register 0x10000 🧚
  • imr β€” HEART_IMR0 to HEART_IMR3 β€” per-cpu interrupt mask register πŸ›‘οΈ
  • set_isr β€” maps to HEART_SET_ISR; set interrupt status register βœ…
  • clear_isr β€” maps to HEART_CLR_ISR; clear interrupt status register 🧹
  • isr β€” maps to HEART_ISR; interrupt status register (read-only) πŸ‘€
  • imsr β€” maps to HEART_IMSR; purpose unknown πŸ€·β€β™€οΈ
  • cause β€” maps to HEART_CAUSE; HEART cause information πŸ”
  • __pad2 β€” 0xffb8 bytes of padding -> next HEART register 0x20000 🧚
  • count β€” maps to HEART_COUNT; 52-bit counter πŸ”’
  • __pad3 β€” 0xfff8 bytes of padding -> next HEART register 0x30000 🧚
  • compare β€” maps to HEART_COMPARE; 24-bit compare βš–οΈ
  • __pad4 β€” 0xfff8 bytes of padding -> next HEART register 0x40000 🧚
  • trigger β€” maps to HEART_TRIGGER; purpose unknown 🎯
  • __pad5 β€” 0xfff8 bytes of padding -> next HEART register 0x50000 🧚
  • cpuid β€” maps to HEART_PRID; contains CPU ID of CPU currently accessing HEART πŸͺͺ
  • __pad6 β€” 0xfff8 bytes of padding -> next HEART register 0x60000 🧚
  • sync β€” maps to HEART_SYNC; purpose unknown πŸ”„

🌸 DESCRIPTION 🌸

HEART is the main system controller ASIC for the IP30 system. It incorporates a memory controller, interrupt status/cause/set/clear management, basic timer with count/compare, and other functionality. For Linux, not all of HEART’s functions are fully understood 😭

Implementation note: All HEART registers are 64bits-wide, but the mem_cfg register only reports correct values if queried in 32bits. Hence the need for a union. Even though mem_cfg.l has 8 array slots, we only ever query up to 4 of those. IP30 has 8 DIMM slots arranged into 4 banks, w/ 2 DIMMs per bank. Each 32bit read accesses one of these banks. Perhaps HEART was designed to address up to 8 banks (16 DIMMs)? We may never know πŸ€”πŸ’­


πŸ‘‘ SEE ALSO πŸ‘‘

  • Kernel file ./arch/mips/include/asm/sgi/heart.h πŸ“–βœ¨

mwah πŸ’‹ this page lives in ./arch/mips/include/asm/sgi, dated October 2026, and it’s literally the struct ip30_heart_regs(9) manual. byeee bestie 🫢🌈

πŸ“¦ where this page comes from