^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * PS3 Logical Performance Monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2007 Sony Computer Entertainment Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2007 Sony Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/ps3.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/lv1call.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/cell-pmu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* BOOKMARK tag macros */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define PS3_PM_BOOKMARK_START 0x8000000000000000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PS3_PM_BOOKMARK_STOP 0x4000000000000000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define PS3_PM_BOOKMARK_TAG_KERNEL 0x1000000000000000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define PS3_PM_BOOKMARK_TAG_USER 0x3000000000000000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define PS3_PM_BOOKMARK_TAG_MASK_HI 0xF000000000000000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define PS3_PM_BOOKMARK_TAG_MASK_LO 0x0F00000000000000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* CBE PM CONTROL register macros */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define PS3_PM_CONTROL_PPU_TH0_BOOKMARK 0x00001000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define PS3_PM_CONTROL_PPU_TH1_BOOKMARK 0x00000800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define PS3_PM_CONTROL_PPU_COUNT_MODE_MASK 0x000C0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define PS3_PM_CONTROL_PPU_COUNT_MODE_PROBLEM 0x00080000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define PS3_WRITE_PM_MASK 0xFFFFFFFFFFFFFFFFULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* CBE PM START STOP register macros */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define PS3_PM_START_STOP_PPU_TH0_BOOKMARK_START 0x02000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define PS3_PM_START_STOP_PPU_TH1_BOOKMARK_START 0x01000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define PS3_PM_START_STOP_PPU_TH0_BOOKMARK_STOP 0x00020000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define PS3_PM_START_STOP_PPU_TH1_BOOKMARK_STOP 0x00010000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define PS3_PM_START_STOP_START_MASK 0xFF000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define PS3_PM_START_STOP_STOP_MASK 0x00FF0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* CBE PM COUNTER register macres */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define PS3_PM_COUNTER_MASK_HI 0xFFFFFFFF00000000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define PS3_PM_COUNTER_MASK_LO 0x00000000FFFFFFFFULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* BASE SIGNAL GROUP NUMBER macros */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define PM_ISLAND2_BASE_SIGNAL_GROUP_NUMBER 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define PM_ISLAND2_SIGNAL_GROUP_NUMBER1 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define PM_ISLAND2_SIGNAL_GROUP_NUMBER2 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define PM_ISLAND3_BASE_SIGNAL_GROUP_NUMBER 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define PM_ISLAND4_BASE_SIGNAL_GROUP_NUMBER 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define PM_SPU_TRIGGER_SIGNAL_GROUP_NUMBER 17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define PM_SPU_EVENT_SIGNAL_GROUP_NUMBER 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define PM_ISLAND5_BASE_SIGNAL_GROUP_NUMBER 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define PM_ISLAND6_BASE_SIGNAL_GROUP_NUMBER 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define PM_ISLAND7_BASE_SIGNAL_GROUP_NUMBER 49
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define PM_ISLAND8_BASE_SIGNAL_GROUP_NUMBER 52
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define PM_SIG_GROUP_SPU 41
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define PM_SIG_GROUP_SPU_TRIGGER 42
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define PM_SIG_GROUP_SPU_EVENT 43
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define PM_SIG_GROUP_MFC_MAX 60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * struct ps3_lpm_shadow_regs - Performance monitor shadow registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * @pm_control: Shadow of the processor's pm_control register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * @pm_start_stop: Shadow of the processor's pm_start_stop register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * @group_control: Shadow of the processor's group_control register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * @debug_bus_control: Shadow of the processor's debug_bus_control register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * The logical performance monitor provides a write-only interface to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * these processor registers. These shadow variables cache the processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * register values for reading.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * The initial value of the shadow registers at lpm creation is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * PS3_LPM_SHADOW_REG_INIT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct ps3_lpm_shadow_regs {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) u64 pm_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) u64 pm_start_stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u64 group_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) u64 debug_bus_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define PS3_LPM_SHADOW_REG_INIT 0xFFFFFFFF00000000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * struct ps3_lpm_priv - Private lpm device data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * @open: An atomic variable indicating the lpm driver has been opened.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * @rights: The lpm rigths granted by the system policy module. A logical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * OR of enum ps3_lpm_rights.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * @node_id: The node id of a BE processor whose performance monitor this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * lpar has the right to use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * @pu_id: The lv1 id of the logical PU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * @lpm_id: The lv1 id of this lpm instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * @outlet_id: The outlet created by lv1 for this lpm instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * @tb_count: The number of bytes of data held in the lv1 trace buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * @tb_cache: Kernel buffer to receive the data from the lv1 trace buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * Must be 128 byte aligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @tb_cache_size: Size of the kernel @tb_cache buffer. Must be 128 byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * aligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * @tb_cache_internal: An unaligned buffer allocated by this driver to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * used for the trace buffer cache when ps3_lpm_open() is called with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * NULL tb_cache argument. Otherwise unused.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @shadow: Processor register shadow of type struct ps3_lpm_shadow_regs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * @sbd: The struct ps3_system_bus_device attached to this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * The trace buffer is a buffer allocated and used internally to the lv1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * hypervisor to collect trace data. The trace buffer cache is a guest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * buffer that accepts the trace data from the trace buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct ps3_lpm_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) atomic_t open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) u64 rights;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u64 node_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) u64 pu_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u64 lpm_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) u64 outlet_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) u64 tb_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) void *tb_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) u64 tb_cache_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) void *tb_cache_internal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct ps3_lpm_shadow_regs shadow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct ps3_system_bus_device *sbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) PS3_LPM_DEFAULT_TB_CACHE_SIZE = 0x4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * lpm_priv - Static instance of the lpm data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * Since the exported routines don't support the notion of a device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * instance we need to hold the instance in this static variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * and then only allow at most one instance at a time to be created.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static struct ps3_lpm_priv *lpm_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static struct device *sbd_core(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) BUG_ON(!lpm_priv || !lpm_priv->sbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return &lpm_priv->sbd->core;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * use_start_stop_bookmark - Enable the PPU bookmark trace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * And it enables PPU bookmark triggers ONLY if the other triggers are not set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * The start/stop bookmarks are inserted at ps3_enable_pm() and ps3_disable_pm()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * to start/stop LPM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * Used to get good quality of the performance counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) enum {use_start_stop_bookmark = 1,};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) void ps3_set_bookmark(u64 bookmark)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * As per the PPE book IV, to avoid bookmark loss there must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * not be a traced branch within 10 cycles of setting the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * SPRN_BKMK register. The actual text is unclear if 'within'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * includes cycles before the call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) asm volatile("nop;nop;nop;nop;nop;nop;nop;nop;nop;");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) mtspr(SPRN_BKMK, bookmark);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) asm volatile("nop;nop;nop;nop;nop;nop;nop;nop;nop;");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) EXPORT_SYMBOL_GPL(ps3_set_bookmark);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) void ps3_set_pm_bookmark(u64 tag, u64 incident, u64 th_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) u64 bookmark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) bookmark = (get_tb() & 0x00000000FFFFFFFFULL) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) PS3_PM_BOOKMARK_TAG_KERNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) bookmark = ((tag << 56) & PS3_PM_BOOKMARK_TAG_MASK_LO) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) (incident << 48) | (th_id << 32) | bookmark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ps3_set_bookmark(bookmark);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) EXPORT_SYMBOL_GPL(ps3_set_pm_bookmark);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * ps3_read_phys_ctr - Read physical counter registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * Each physical counter can act as one 32 bit counter or as two 16 bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * counters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u32 ps3_read_phys_ctr(u32 cpu, u32 phys_ctr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) u64 counter0415;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) u64 counter2637;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (phys_ctr >= NR_PHYS_CTRS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) __LINE__, phys_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) result = lv1_set_lpm_counter(lpm_priv->lpm_id, 0, 0, 0, 0, &counter0415,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) &counter2637);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) dev_err(sbd_core(), "%s:%u: lv1_set_lpm_counter failed: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) "phys_ctr %u, %s\n", __func__, __LINE__, phys_ctr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ps3_result(result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) switch (phys_ctr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return counter0415 >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return counter0415 & PS3_PM_COUNTER_MASK_LO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return counter2637 >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return counter2637 & PS3_PM_COUNTER_MASK_LO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) EXPORT_SYMBOL_GPL(ps3_read_phys_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * ps3_write_phys_ctr - Write physical counter registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * Each physical counter can act as one 32 bit counter or as two 16 bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * counters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) void ps3_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) u64 counter0415;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) u64 counter0415_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) u64 counter2637;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) u64 counter2637_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (phys_ctr >= NR_PHYS_CTRS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) __LINE__, phys_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) switch (phys_ctr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) counter0415 = (u64)val << 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) counter0415_mask = PS3_PM_COUNTER_MASK_HI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) counter2637 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) counter2637_mask = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) counter0415 = (u64)val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) counter0415_mask = PS3_PM_COUNTER_MASK_LO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) counter2637 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) counter2637_mask = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) counter0415 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) counter0415_mask = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) counter2637 = (u64)val << 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) counter2637_mask = PS3_PM_COUNTER_MASK_HI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) counter0415 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) counter0415_mask = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) counter2637 = (u64)val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) counter2637_mask = PS3_PM_COUNTER_MASK_LO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) result = lv1_set_lpm_counter(lpm_priv->lpm_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) counter0415, counter0415_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) counter2637, counter2637_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) &counter0415, &counter2637);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) dev_err(sbd_core(), "%s:%u: lv1_set_lpm_counter failed: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) "phys_ctr %u, val %u, %s\n", __func__, __LINE__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) phys_ctr, val, ps3_result(result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) EXPORT_SYMBOL_GPL(ps3_write_phys_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * ps3_read_ctr - Read counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * Read 16 or 32 bits depending on the current size of the counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * Counters 4, 5, 6 & 7 are always 16 bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) u32 ps3_read_ctr(u32 cpu, u32 ctr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) u32 phys_ctr = ctr & (NR_PHYS_CTRS - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) val = ps3_read_phys_ctr(cpu, phys_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (ps3_get_ctr_size(cpu, phys_ctr) == 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) val = (ctr < NR_PHYS_CTRS) ? (val >> 16) : (val & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) EXPORT_SYMBOL_GPL(ps3_read_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * ps3_write_ctr - Write counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * Write 16 or 32 bits depending on the current size of the counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * Counters 4, 5, 6 & 7 are always 16 bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) void ps3_write_ctr(u32 cpu, u32 ctr, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) u32 phys_ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) u32 phys_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) phys_ctr = ctr & (NR_PHYS_CTRS - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (ps3_get_ctr_size(cpu, phys_ctr) == 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) phys_val = ps3_read_phys_ctr(cpu, phys_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (ctr < NR_PHYS_CTRS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) val = (val << 16) | (phys_val & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) val = (val & 0xffff) | (phys_val & 0xffff0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) ps3_write_phys_ctr(cpu, phys_ctr, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) EXPORT_SYMBOL_GPL(ps3_write_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * ps3_read_pm07_control - Read counter control registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * Each logical counter has a corresponding control register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) u32 ps3_read_pm07_control(u32 cpu, u32 ctr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) EXPORT_SYMBOL_GPL(ps3_read_pm07_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * ps3_write_pm07_control - Write counter control registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * Each logical counter has a corresponding control register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) void ps3_write_pm07_control(u32 cpu, u32 ctr, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static const u64 mask = 0xFFFFFFFFFFFFFFFFULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) u64 old_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (ctr >= NR_CTRS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) dev_dbg(sbd_core(), "%s:%u: ctr too big: %u\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) __LINE__, ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) result = lv1_set_lpm_counter_control(lpm_priv->lpm_id, ctr, val, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) &old_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) dev_err(sbd_core(), "%s:%u: lv1_set_lpm_counter_control "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) "failed: ctr %u, %s\n", __func__, __LINE__, ctr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) ps3_result(result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) EXPORT_SYMBOL_GPL(ps3_write_pm07_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * ps3_read_pm - Read Other LPM control registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) u32 ps3_read_pm(u32 cpu, enum pm_reg_name reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) u64 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) case pm_control:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return lpm_priv->shadow.pm_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) case trace_address:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return CBE_PM_TRACE_BUF_EMPTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) case pm_start_stop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return lpm_priv->shadow.pm_start_stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) case pm_interval:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) result = lv1_set_lpm_interval(lpm_priv->lpm_id, 0, 0, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) dev_dbg(sbd_core(), "%s:%u: lv1 set_interval failed: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) "reg %u, %s\n", __func__, __LINE__, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) ps3_result(result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return (u32)val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) case group_control:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return lpm_priv->shadow.group_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) case debug_bus_control:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return lpm_priv->shadow.debug_bus_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) case pm_status:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) result = lv1_get_lpm_interrupt_status(lpm_priv->lpm_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) dev_dbg(sbd_core(), "%s:%u: lv1 get_lpm_status failed: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) "reg %u, %s\n", __func__, __LINE__, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) ps3_result(result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return (u32)val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) case ext_tr_timer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) dev_dbg(sbd_core(), "%s:%u: unknown reg: %d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) __LINE__, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) EXPORT_SYMBOL_GPL(ps3_read_pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * ps3_write_pm - Write Other LPM control registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) void ps3_write_pm(u32 cpu, enum pm_reg_name reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) u64 dummy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) case group_control:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (val != lpm_priv->shadow.group_control)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) result = lv1_set_lpm_group_control(lpm_priv->lpm_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) PS3_WRITE_PM_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) &dummy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) lpm_priv->shadow.group_control = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) case debug_bus_control:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (val != lpm_priv->shadow.debug_bus_control)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) result = lv1_set_lpm_debug_bus_control(lpm_priv->lpm_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) PS3_WRITE_PM_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) &dummy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) lpm_priv->shadow.debug_bus_control = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) case pm_control:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (use_start_stop_bookmark)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) val |= (PS3_PM_CONTROL_PPU_TH0_BOOKMARK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) PS3_PM_CONTROL_PPU_TH1_BOOKMARK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (val != lpm_priv->shadow.pm_control)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) result = lv1_set_lpm_general_control(lpm_priv->lpm_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) PS3_WRITE_PM_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 0, 0, &dummy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) &dummy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) lpm_priv->shadow.pm_control = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) case pm_interval:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) result = lv1_set_lpm_interval(lpm_priv->lpm_id, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) PS3_WRITE_PM_MASK, &dummy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) case pm_start_stop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (val != lpm_priv->shadow.pm_start_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) result = lv1_set_lpm_trigger_control(lpm_priv->lpm_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) PS3_WRITE_PM_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) &dummy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) lpm_priv->shadow.pm_start_stop = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) case trace_address:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) case ext_tr_timer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) case pm_status:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) dev_dbg(sbd_core(), "%s:%u: unknown reg: %d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) __LINE__, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) dev_err(sbd_core(), "%s:%u: lv1 set_control failed: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) "reg %u, %s\n", __func__, __LINE__, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ps3_result(result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) EXPORT_SYMBOL_GPL(ps3_write_pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * ps3_get_ctr_size - Get the size of a physical counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * Returns either 16 or 32.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) u32 ps3_get_ctr_size(u32 cpu, u32 phys_ctr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) u32 pm_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (phys_ctr >= NR_PHYS_CTRS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) __LINE__, phys_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) pm_ctrl = ps3_read_pm(cpu, pm_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return (pm_ctrl & CBE_PM_16BIT_CTR(phys_ctr)) ? 16 : 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) EXPORT_SYMBOL_GPL(ps3_get_ctr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * ps3_set_ctr_size - Set the size of a physical counter to 16 or 32 bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) void ps3_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) u32 pm_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (phys_ctr >= NR_PHYS_CTRS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) __LINE__, phys_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) pm_ctrl = ps3_read_pm(cpu, pm_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) switch (ctr_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) pm_ctrl |= CBE_PM_16BIT_CTR(phys_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ps3_write_pm(cpu, pm_control, pm_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) pm_ctrl &= ~CBE_PM_16BIT_CTR(phys_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) ps3_write_pm(cpu, pm_control, pm_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) EXPORT_SYMBOL_GPL(ps3_set_ctr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static u64 pm_translate_signal_group_number_on_island2(u64 subgroup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (subgroup == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) subgroup = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (subgroup <= 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return PM_ISLAND2_BASE_SIGNAL_GROUP_NUMBER + subgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) else if (subgroup == 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return PM_ISLAND2_SIGNAL_GROUP_NUMBER1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return PM_ISLAND2_SIGNAL_GROUP_NUMBER2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static u64 pm_translate_signal_group_number_on_island3(u64 subgroup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) switch (subgroup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) subgroup += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) subgroup = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return PM_ISLAND3_BASE_SIGNAL_GROUP_NUMBER + subgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static u64 pm_translate_signal_group_number_on_island4(u64 subgroup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return PM_ISLAND4_BASE_SIGNAL_GROUP_NUMBER + subgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static u64 pm_translate_signal_group_number_on_island5(u64 subgroup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) switch (subgroup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) subgroup = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) subgroup = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return PM_ISLAND5_BASE_SIGNAL_GROUP_NUMBER + subgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static u64 pm_translate_signal_group_number_on_island6(u64 subgroup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) u64 subsubgroup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) switch (subgroup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) subgroup += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) switch (subsubgroup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) subsubgroup += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) case 9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) case 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) subsubgroup += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) case 11:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) case 12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) case 13:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) subsubgroup += 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (subgroup <= 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return (PM_ISLAND6_BASE_SIGNAL_GROUP_NUMBER + subgroup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) return (PM_ISLAND6_BASE_SIGNAL_GROUP_NUMBER + subgroup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) + subsubgroup - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static u64 pm_translate_signal_group_number_on_island7(u64 subgroup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return PM_ISLAND7_BASE_SIGNAL_GROUP_NUMBER + subgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static u64 pm_translate_signal_group_number_on_island8(u64 subgroup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return PM_ISLAND8_BASE_SIGNAL_GROUP_NUMBER + subgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) static u64 pm_signal_group_to_ps3_lv1_signal_group(u64 group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) u64 island;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) u64 subgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) u64 subsubgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) subgroup = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) subsubgroup = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) island = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (group < 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (group < 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (20 <= group && group < 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) island = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) subgroup = group - 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) } else if (30 <= group && group < 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) island = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) subgroup = group - 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) } else if (40 <= group && group < 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) island = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) subgroup = group - 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) } else if (50 <= group && group < 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) island = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) subgroup = group - 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) } else if (60 <= group && group < 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) island = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) subgroup = group - 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) } else if (70 <= group && group < 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) island = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) subgroup = group - 70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) } else if (80 <= group && group < 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) island = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) subgroup = group - 80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) } else if (200 <= group && group < 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) island = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) subgroup = group - 200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) } else if (600 <= group && group < 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) island = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) subgroup = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) subsubgroup = group - 650;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) } else if (6000 <= group && group < 7000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) island = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) subgroup = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) subsubgroup = group - 6500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) switch (island) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return pm_translate_signal_group_number_on_island2(subgroup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return pm_translate_signal_group_number_on_island3(subgroup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return pm_translate_signal_group_number_on_island4(subgroup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return pm_translate_signal_group_number_on_island5(subgroup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return pm_translate_signal_group_number_on_island6(subgroup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) subsubgroup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return pm_translate_signal_group_number_on_island7(subgroup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return pm_translate_signal_group_number_on_island8(subgroup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) dev_dbg(sbd_core(), "%s:%u: island not found: %llu\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) __LINE__, group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) static u64 pm_bus_word_to_ps3_lv1_bus_word(u8 word)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) switch (word) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return 0xF000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return 0x0F00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return 0x00F0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return 0x000F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static int __ps3_set_signal(u64 lv1_signal_group, u64 bus_select,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) u64 signal_select, u64 attr1, u64 attr2, u64 attr3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) ret = lv1_set_lpm_signal(lpm_priv->lpm_id, lv1_signal_group, bus_select,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) signal_select, attr1, attr2, attr3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) dev_err(sbd_core(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) "%s:%u: error:%d 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) __func__, __LINE__, ret, lv1_signal_group, bus_select,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) signal_select, attr1, attr2, attr3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) int ps3_set_signal(u64 signal_group, u8 signal_bit, u16 sub_unit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) u8 bus_word)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) u64 lv1_signal_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) u64 bus_select;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) u64 signal_select;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) u64 attr1, attr2, attr3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (signal_group == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return __ps3_set_signal(0, 0, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) lv1_signal_group =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) pm_signal_group_to_ps3_lv1_signal_group(signal_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) bus_select = pm_bus_word_to_ps3_lv1_bus_word(bus_word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) switch (signal_group) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) case PM_SIG_GROUP_SPU_TRIGGER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) signal_select = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) signal_select = signal_select << (63 - signal_bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) case PM_SIG_GROUP_SPU_EVENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) signal_select = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) signal_select = (signal_select << (63 - signal_bit)) | 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) signal_select = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * 0: physical object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * 1: logical object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * This parameter is only used for the PPE and SPE signals.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) attr1 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * This parameter is used to specify the target physical/logical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * PPE/SPE object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (PM_SIG_GROUP_SPU <= signal_group &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) signal_group < PM_SIG_GROUP_MFC_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) attr2 = sub_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) attr2 = lpm_priv->pu_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * This parameter is only used for setting the SPE signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) attr3 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) ret = __ps3_set_signal(lv1_signal_group, bus_select, signal_select,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) attr1, attr2, attr3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) dev_err(sbd_core(), "%s:%u: __ps3_set_signal failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) __func__, __LINE__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) EXPORT_SYMBOL_GPL(ps3_set_signal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) u32 ps3_get_hw_thread_id(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return get_hard_smp_processor_id(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) EXPORT_SYMBOL_GPL(ps3_get_hw_thread_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * ps3_enable_pm - Enable the entire performance monitoring unit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * When we enable the LPM, all pending writes to counters get committed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) void ps3_enable_pm(u32 cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) u64 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) int insert_bookmark = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) lpm_priv->tb_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (use_start_stop_bookmark) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (!(lpm_priv->shadow.pm_start_stop &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) (PS3_PM_START_STOP_START_MASK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) | PS3_PM_START_STOP_STOP_MASK))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) result = lv1_set_lpm_trigger_control(lpm_priv->lpm_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) (PS3_PM_START_STOP_PPU_TH0_BOOKMARK_START |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) PS3_PM_START_STOP_PPU_TH1_BOOKMARK_START |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) PS3_PM_START_STOP_PPU_TH0_BOOKMARK_STOP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) PS3_PM_START_STOP_PPU_TH1_BOOKMARK_STOP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 0xFFFFFFFFFFFFFFFFULL, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) dev_err(sbd_core(), "%s:%u: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) "lv1_set_lpm_trigger_control failed: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) "%s\n", __func__, __LINE__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) ps3_result(result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) insert_bookmark = !result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) result = lv1_start_lpm(lpm_priv->lpm_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) dev_err(sbd_core(), "%s:%u: lv1_start_lpm failed: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) __func__, __LINE__, ps3_result(result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (use_start_stop_bookmark && !result && insert_bookmark)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) ps3_set_bookmark(get_tb() | PS3_PM_BOOKMARK_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) EXPORT_SYMBOL_GPL(ps3_enable_pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * ps3_disable_pm - Disable the entire performance monitoring unit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) void ps3_disable_pm(u32 cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) u64 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) ps3_set_bookmark(get_tb() | PS3_PM_BOOKMARK_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) result = lv1_stop_lpm(lpm_priv->lpm_id, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (result != LV1_WRONG_STATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) dev_err(sbd_core(), "%s:%u: lv1_stop_lpm failed: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) __func__, __LINE__, ps3_result(result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) lpm_priv->tb_count = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) dev_dbg(sbd_core(), "%s:%u: tb_count %llu (%llxh)\n", __func__, __LINE__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) lpm_priv->tb_count, lpm_priv->tb_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) EXPORT_SYMBOL_GPL(ps3_disable_pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) * ps3_lpm_copy_tb - Copy data from the trace buffer to a kernel buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) * @offset: Offset in bytes from the start of the trace buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) * @buf: Copy destination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) * @count: Maximum count of bytes to copy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * @bytes_copied: Pointer to a variable that will receive the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) * bytes copied to @buf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) * On error @buf will contain any successfully copied trace buffer data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * and bytes_copied will be set to the number of bytes successfully copied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) int ps3_lpm_copy_tb(unsigned long offset, void *buf, unsigned long count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) unsigned long *bytes_copied)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) *bytes_copied = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (!lpm_priv->tb_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (offset >= lpm_priv->tb_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) count = min_t(u64, count, lpm_priv->tb_count - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) while (*bytes_copied < count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) const unsigned long request = count - *bytes_copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) u64 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) result = lv1_copy_lpm_trace_buffer(lpm_priv->lpm_id, offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) request, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) dev_dbg(sbd_core(), "%s:%u: 0x%lx bytes at 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) __func__, __LINE__, request, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) dev_err(sbd_core(), "%s:%u: lv1_copy_lpm_trace_buffer "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) "failed: %s\n", __func__, __LINE__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) ps3_result(result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) return result == LV1_WRONG_STATE ? -EBUSY : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) memcpy(buf, lpm_priv->tb_cache, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) buf += tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) *bytes_copied += tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) offset += tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) dev_dbg(sbd_core(), "%s:%u: copied %lxh bytes\n", __func__, __LINE__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) *bytes_copied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) EXPORT_SYMBOL_GPL(ps3_lpm_copy_tb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) * ps3_lpm_copy_tb_to_user - Copy data from the trace buffer to a user buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * @offset: Offset in bytes from the start of the trace buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * @buf: A __user copy destination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * @count: Maximum count of bytes to copy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) * @bytes_copied: Pointer to a variable that will receive the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * bytes copied to @buf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * On error @buf will contain any successfully copied trace buffer data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * and bytes_copied will be set to the number of bytes successfully copied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) int ps3_lpm_copy_tb_to_user(unsigned long offset, void __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) unsigned long count, unsigned long *bytes_copied)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) *bytes_copied = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (!lpm_priv->tb_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (offset >= lpm_priv->tb_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) count = min_t(u64, count, lpm_priv->tb_count - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) while (*bytes_copied < count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) const unsigned long request = count - *bytes_copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) u64 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) result = lv1_copy_lpm_trace_buffer(lpm_priv->lpm_id, offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) request, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) dev_dbg(sbd_core(), "%s:%u: 0x%lx bytes at 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) __func__, __LINE__, request, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) dev_err(sbd_core(), "%s:%u: lv1_copy_lpm_trace_buffer "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) "failed: %s\n", __func__, __LINE__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) ps3_result(result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) return result == LV1_WRONG_STATE ? -EBUSY : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) result = copy_to_user(buf, lpm_priv->tb_cache, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) dev_dbg(sbd_core(), "%s:%u: 0x%llx bytes at 0x%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) __func__, __LINE__, tmp, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) dev_err(sbd_core(), "%s:%u: copy_to_user failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) __func__, __LINE__, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) buf += tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) *bytes_copied += tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) offset += tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) dev_dbg(sbd_core(), "%s:%u: copied %lxh bytes\n", __func__, __LINE__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) *bytes_copied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) EXPORT_SYMBOL_GPL(ps3_lpm_copy_tb_to_user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * ps3_get_and_clear_pm_interrupts -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) * Clearing interrupts for the entire performance monitoring unit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) * Reading pm_status clears the interrupt bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) u32 ps3_get_and_clear_pm_interrupts(u32 cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) return ps3_read_pm(cpu, pm_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) EXPORT_SYMBOL_GPL(ps3_get_and_clear_pm_interrupts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) * ps3_enable_pm_interrupts -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) * Enabling interrupts for the entire performance monitoring unit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) * Enables the interrupt bits in the pm_status register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) void ps3_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) ps3_write_pm(cpu, pm_status, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) EXPORT_SYMBOL_GPL(ps3_enable_pm_interrupts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) * ps3_enable_pm_interrupts -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) * Disabling interrupts for the entire performance monitoring unit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) void ps3_disable_pm_interrupts(u32 cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) ps3_get_and_clear_pm_interrupts(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) ps3_write_pm(cpu, pm_status, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) EXPORT_SYMBOL_GPL(ps3_disable_pm_interrupts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * ps3_lpm_open - Open the logical performance monitor device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) * @tb_type: Specifies the type of trace buffer lv1 should use for this lpm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) * instance, specified by one of enum ps3_lpm_tb_type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) * @tb_cache: Optional user supplied buffer to use as the trace buffer cache.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) * If NULL, the driver will allocate and manage an internal buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) * Unused when when @tb_type is PS3_LPM_TB_TYPE_NONE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) * @tb_cache_size: The size in bytes of the user supplied @tb_cache buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) * Unused when @tb_cache is NULL or @tb_type is PS3_LPM_TB_TYPE_NONE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) int ps3_lpm_open(enum ps3_lpm_tb_type tb_type, void *tb_cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) u64 tb_cache_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) u64 tb_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) BUG_ON(!lpm_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) BUG_ON(tb_type != PS3_LPM_TB_TYPE_NONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) && tb_type != PS3_LPM_TB_TYPE_INTERNAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (tb_type == PS3_LPM_TB_TYPE_NONE && tb_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) dev_dbg(sbd_core(), "%s:%u: bad in vals\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (!atomic_add_unless(&lpm_priv->open, 1, 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) dev_dbg(sbd_core(), "%s:%u: busy\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) /* Note tb_cache needs 128 byte alignment. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (tb_type == PS3_LPM_TB_TYPE_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) lpm_priv->tb_cache_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) lpm_priv->tb_cache_internal = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) lpm_priv->tb_cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) } else if (tb_cache) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (tb_cache != (void *)ALIGN((unsigned long)tb_cache, 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) || tb_cache_size != ALIGN(tb_cache_size, 128)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) dev_err(sbd_core(), "%s:%u: unaligned tb_cache\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) result = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) goto fail_align;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) lpm_priv->tb_cache_size = tb_cache_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) lpm_priv->tb_cache_internal = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) lpm_priv->tb_cache = tb_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) lpm_priv->tb_cache_size = PS3_LPM_DEFAULT_TB_CACHE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) lpm_priv->tb_cache_internal = kzalloc(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) lpm_priv->tb_cache_size + 127, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (!lpm_priv->tb_cache_internal) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) result = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) goto fail_malloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) lpm_priv->tb_cache = (void *)ALIGN(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) (unsigned long)lpm_priv->tb_cache_internal, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) result = lv1_construct_lpm(lpm_priv->node_id, tb_type, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) ps3_mm_phys_to_lpar(__pa(lpm_priv->tb_cache)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) lpm_priv->tb_cache_size, &lpm_priv->lpm_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) &lpm_priv->outlet_id, &tb_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) dev_err(sbd_core(), "%s:%u: lv1_construct_lpm failed: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) __func__, __LINE__, ps3_result(result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) result = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) goto fail_construct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) lpm_priv->shadow.pm_control = PS3_LPM_SHADOW_REG_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) lpm_priv->shadow.pm_start_stop = PS3_LPM_SHADOW_REG_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) lpm_priv->shadow.group_control = PS3_LPM_SHADOW_REG_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) lpm_priv->shadow.debug_bus_control = PS3_LPM_SHADOW_REG_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) dev_dbg(sbd_core(), "%s:%u: lpm_id 0x%llx, outlet_id 0x%llx, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) "tb_size 0x%llx\n", __func__, __LINE__, lpm_priv->lpm_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) lpm_priv->outlet_id, tb_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) fail_construct:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) kfree(lpm_priv->tb_cache_internal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) lpm_priv->tb_cache_internal = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) fail_malloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) fail_align:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) atomic_dec(&lpm_priv->open);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) EXPORT_SYMBOL_GPL(ps3_lpm_open);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) * ps3_lpm_close - Close the lpm device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) int ps3_lpm_close(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) dev_dbg(sbd_core(), "%s:%u\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) lv1_destruct_lpm(lpm_priv->lpm_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) lpm_priv->lpm_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) kfree(lpm_priv->tb_cache_internal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) lpm_priv->tb_cache_internal = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) atomic_dec(&lpm_priv->open);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) EXPORT_SYMBOL_GPL(ps3_lpm_close);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) static int ps3_lpm_probe(struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) dev_dbg(&dev->core, " -> %s:%u\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) if (lpm_priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) dev_info(&dev->core, "%s:%u: called twice\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) lpm_priv = kzalloc(sizeof(*lpm_priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) if (!lpm_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) lpm_priv->sbd = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) lpm_priv->node_id = dev->lpm.node_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) lpm_priv->pu_id = dev->lpm.pu_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) lpm_priv->rights = dev->lpm.rights;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) dev_info(&dev->core, " <- %s:%u:\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) static int ps3_lpm_remove(struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) dev_dbg(&dev->core, " -> %s:%u:\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) ps3_lpm_close();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) kfree(lpm_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) lpm_priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) dev_info(&dev->core, " <- %s:%u:\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) static struct ps3_system_bus_driver ps3_lpm_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) .match_id = PS3_MATCH_ID_LPM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) .core.name = "ps3-lpm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) .core.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) .probe = ps3_lpm_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) .remove = ps3_lpm_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) .shutdown = ps3_lpm_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) static int __init ps3_lpm_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) pr_debug("%s:%d:\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return ps3_system_bus_driver_register(&ps3_lpm_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) static void __exit ps3_lpm_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) pr_debug("%s:%d:\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) ps3_system_bus_driver_unregister(&ps3_lpm_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) module_init(ps3_lpm_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) module_exit(ps3_lpm_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) MODULE_DESCRIPTION("PS3 Logical Performance Monitor Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) MODULE_AUTHOR("Sony Corporation");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) MODULE_ALIAS(PS3_MODULE_ALIAS_LPM);