Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 1 | /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. |
| 2 | * |
| 3 | * This program is free software; you can redistribute it and/or modify |
| 4 | * it under the terms of the GNU General Public License version 2 and |
| 5 | * only version 2 as published by the Free Software Foundation. |
| 6 | * |
| 7 | * This program is distributed in the hope that it will be useful, |
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | * GNU General Public License for more details. |
| 11 | */ |
| 12 | #include <linux/err.h> |
| 13 | #include <linux/mutex.h> |
| 14 | #include <linux/list.h> |
Mitchel Humpherys | 9e1f987 | 2013-02-28 13:30:44 -0800 | [diff] [blame] | 15 | #include <linux/irqreturn.h> |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 16 | |
| 17 | #ifndef MSM_IOMMU_PERFMON_H |
| 18 | #define MSM_IOMMU_PERFMON_H |
| 19 | |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 20 | /** |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 21 | * struct iommu_pmon_counter - container for a performance counter. |
| 22 | * @counter_no: counter number within the group |
| 23 | * @absolute_counter_no: counter number within IOMMU PMU |
| 24 | * @value: cached counter value |
| 25 | * @overflow_count: no of times counter has overflowed |
| 26 | * @enabled: indicates whether counter is enabled or not |
| 27 | * @current_event_class: current selected event class, -1 if none |
| 28 | * @counter_dir: debugfs directory for this counter |
| 29 | * @cnt_group: group this counter belongs to |
| 30 | */ |
| 31 | struct iommu_pmon_counter { |
| 32 | unsigned int counter_no; |
| 33 | unsigned int absolute_counter_no; |
| 34 | unsigned long value; |
| 35 | unsigned long overflow_count; |
| 36 | unsigned int enabled; |
| 37 | int current_event_class; |
| 38 | struct dentry *counter_dir; |
| 39 | struct iommu_pmon_cnt_group *cnt_group; |
| 40 | }; |
| 41 | |
| 42 | /** |
| 43 | * struct iommu_pmon_cnt_group - container for a perf mon counter group. |
| 44 | * @grp_no: group number |
| 45 | * @num_counters: number of counters in this group |
| 46 | * @counters: list of counter in this group |
| 47 | * @group_dir: debugfs directory for this group |
| 48 | * @pmon: pointer to the iommu_pmon object this group belongs to |
| 49 | */ |
| 50 | struct iommu_pmon_cnt_group { |
| 51 | unsigned int grp_no; |
| 52 | unsigned int num_counters; |
| 53 | struct iommu_pmon_counter *counters; |
| 54 | struct dentry *group_dir; |
| 55 | struct iommu_pmon *pmon; |
| 56 | }; |
| 57 | |
| 58 | /** |
| 59 | * struct iommu_info - container for a perf mon iommu info. |
| 60 | * @iommu_name: name of the iommu from device tree |
| 61 | * @base: virtual base address for this iommu |
| 62 | * @evt_irq: irq number for event overflow interrupt |
| 63 | * @iommu_dev: pointer to iommu device |
| 64 | * @ops: iommu access operations pointer. |
Olav Haugan | ef69e89 | 2013-02-04 13:47:08 -0800 | [diff] [blame] | 65 | * @hw_ops: iommu pm hw access operations pointer. |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 66 | */ |
| 67 | struct iommu_info { |
| 68 | const char *iommu_name; |
| 69 | void *base; |
| 70 | int evt_irq; |
| 71 | struct device *iommu_dev; |
| 72 | struct iommu_access_ops *ops; |
Olav Haugan | ef69e89 | 2013-02-04 13:47:08 -0800 | [diff] [blame] | 73 | struct iommu_pm_hw_ops *hw_ops; |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 74 | }; |
| 75 | |
| 76 | /** |
| 77 | * struct iommu_pmon - main container for a perf mon data. |
| 78 | * @iommu_dir: debugfs directory for this iommu |
| 79 | * @iommu: iommu_info instance |
| 80 | * @iommu_list: iommu_list head |
| 81 | * @cnt_grp: list of counter groups |
| 82 | * @num_groups: number of counter groups |
Olav Haugan | 0c2d932 | 2013-01-31 18:35:30 -0800 | [diff] [blame] | 83 | * @num_counters: number of counters per group |
| 84 | * @event_cls_supported: an array of event classes supported for this PMU |
| 85 | * @nevent_cls_supported: number of event classes supported. |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 86 | * @enabled: Indicates whether perf. mon is enabled or not |
| 87 | * @iommu_attached Indicates whether iommu is attached or not. |
| 88 | * @lock: mutex used to synchronize access to shared data |
| 89 | */ |
| 90 | struct iommu_pmon { |
| 91 | struct dentry *iommu_dir; |
| 92 | struct iommu_info iommu; |
| 93 | struct list_head iommu_list; |
| 94 | struct iommu_pmon_cnt_group *cnt_grp; |
Olav Haugan | 0c2d932 | 2013-01-31 18:35:30 -0800 | [diff] [blame] | 95 | u32 num_groups; |
| 96 | u32 num_counters; |
| 97 | u32 *event_cls_supported; |
| 98 | u32 nevent_cls_supported; |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 99 | unsigned int enabled; |
| 100 | unsigned int iommu_attach_count; |
| 101 | struct mutex lock; |
| 102 | }; |
| 103 | |
Olav Haugan | ef69e89 | 2013-02-04 13:47:08 -0800 | [diff] [blame] | 104 | /** |
| 105 | * struct iommu_hw_ops - Callbacks for accessing IOMMU HW |
Olav Haugan | 7a2f99c | 2013-02-04 14:43:26 -0800 | [diff] [blame] | 106 | * @initialize_hw: Call to do any initialization before enabling ovf interrupts |
Olav Haugan | ef69e89 | 2013-02-04 13:47:08 -0800 | [diff] [blame] | 107 | * @is_hw_access_ok: Returns 1 if we can access HW, 0 otherwise |
| 108 | * @grp_enable: Call to enable a counter group |
| 109 | * @grp_disable: Call to disable a counter group |
| 110 | * @enable_pm: Call to enable PM |
| 111 | * @disable_pm: Call to disable PM |
| 112 | * @reset_counters: Call to reset counters |
| 113 | * @check_for_overflow: Call to check for overflow |
| 114 | * @evt_ovfl_int_handler: Overflow interrupt handler callback |
| 115 | * @counter_enable: Call to enable counters |
| 116 | * @counter_disable: Call to disable counters |
| 117 | * @ovfl_int_enable: Call to enable overflow interrupts |
| 118 | * @ovfl_int_disable: Call to disable overflow interrupts |
| 119 | * @set_event_class: Call to set event class |
| 120 | * @read_counter: Call to read a counter value |
| 121 | */ |
| 122 | struct iommu_pm_hw_ops { |
Olav Haugan | 7a2f99c | 2013-02-04 14:43:26 -0800 | [diff] [blame] | 123 | void (*initialize_hw)(const struct iommu_pmon *); |
Olav Haugan | ef69e89 | 2013-02-04 13:47:08 -0800 | [diff] [blame] | 124 | unsigned int (*is_hw_access_OK)(const struct iommu_pmon *); |
| 125 | void (*grp_enable)(struct iommu_info *, unsigned int); |
| 126 | void (*grp_disable)(struct iommu_info *, unsigned int); |
| 127 | void (*enable_pm)(struct iommu_info *); |
| 128 | void (*disable_pm)(struct iommu_info *); |
| 129 | void (*reset_counters)(const struct iommu_info *); |
| 130 | void (*check_for_overflow)(struct iommu_pmon *); |
| 131 | irqreturn_t (*evt_ovfl_int_handler)(int, void *); |
| 132 | void (*counter_enable)(struct iommu_info *, |
| 133 | struct iommu_pmon_counter *); |
| 134 | void (*counter_disable)(struct iommu_info *, |
| 135 | struct iommu_pmon_counter *); |
| 136 | void (*ovfl_int_enable)(struct iommu_info *, |
| 137 | const struct iommu_pmon_counter *); |
| 138 | void (*ovfl_int_disable)(struct iommu_info *, |
| 139 | const struct iommu_pmon_counter *); |
| 140 | void (*set_event_class)(struct iommu_pmon *pmon, unsigned int, |
| 141 | unsigned int); |
| 142 | unsigned int (*read_counter)(struct iommu_pmon_counter *); |
| 143 | }; |
| 144 | |
Olav Haugan | 7a2f99c | 2013-02-04 14:43:26 -0800 | [diff] [blame] | 145 | extern struct iommu_access_ops iommu_access_ops_v0; |
Olav Haugan | ef69e89 | 2013-02-04 13:47:08 -0800 | [diff] [blame] | 146 | extern struct iommu_access_ops iommu_access_ops_v1; |
Olav Haugan | 7a2f99c | 2013-02-04 14:43:26 -0800 | [diff] [blame] | 147 | #define MSM_IOMMU_PMU_NO_EVENT_CLASS -1 |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 148 | |
| 149 | #ifdef CONFIG_MSM_IOMMU_PMON |
Olav Haugan | ef69e89 | 2013-02-04 13:47:08 -0800 | [diff] [blame] | 150 | |
| 151 | /** |
Olav Haugan | 7a2f99c | 2013-02-04 14:43:26 -0800 | [diff] [blame] | 152 | * Get pointer to PMU hardware access functions for IOMMUv0 PMU |
| 153 | */ |
| 154 | struct iommu_pm_hw_ops *iommu_pm_get_hw_ops_v0(void); |
| 155 | |
| 156 | /** |
Olav Haugan | ef69e89 | 2013-02-04 13:47:08 -0800 | [diff] [blame] | 157 | * Get pointer to PMU hardware access functions for IOMMUv1 PMU |
| 158 | */ |
| 159 | struct iommu_pm_hw_ops *iommu_pm_get_hw_ops_v1(void); |
| 160 | |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 161 | /** |
| 162 | * Allocate memory for performance monitor structure. Must |
Olav Haugan | 0c2d932 | 2013-01-31 18:35:30 -0800 | [diff] [blame] | 163 | * be called before iommu_pm_iommu_register |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 164 | */ |
Olav Haugan | 0c2d932 | 2013-01-31 18:35:30 -0800 | [diff] [blame] | 165 | struct iommu_pmon *msm_iommu_pm_alloc(struct device *iommu_dev); |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 166 | |
| 167 | /** |
| 168 | * Free memory previously allocated with iommu_pm_alloc |
| 169 | */ |
| 170 | void msm_iommu_pm_free(struct device *iommu_dev); |
| 171 | |
| 172 | /** |
| 173 | * Register iommu with the performance monitor module. |
| 174 | */ |
Olav Haugan | 0c2d932 | 2013-01-31 18:35:30 -0800 | [diff] [blame] | 175 | int msm_iommu_pm_iommu_register(struct iommu_pmon *info); |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 176 | |
| 177 | /** |
| 178 | * Unregister iommu with the performance monitor module. |
| 179 | */ |
| 180 | void msm_iommu_pm_iommu_unregister(struct device *dev); |
| 181 | |
| 182 | /** |
| 183 | * Called by iommu driver when attaching is complete |
| 184 | * Must NOT be called with IOMMU mutexes held. |
| 185 | * @param iommu_dev IOMMU device that is attached |
| 186 | */ |
| 187 | void msm_iommu_attached(struct device *dev); |
| 188 | |
| 189 | /** |
| 190 | * Called by iommu driver before detaching. |
| 191 | * Must NOT be called with IOMMU mutexes held. |
| 192 | * @param iommu_dev IOMMU device that is going to be detached |
| 193 | */ |
| 194 | void msm_iommu_detached(struct device *dev); |
| 195 | #else |
Olav Haugan | 7a2f99c | 2013-02-04 14:43:26 -0800 | [diff] [blame] | 196 | static inline struct iommu_pm_hw_ops *iommu_pm_get_hw_ops_v0(void) |
| 197 | { |
| 198 | return NULL; |
| 199 | } |
| 200 | |
Olav Haugan | ef69e89 | 2013-02-04 13:47:08 -0800 | [diff] [blame] | 201 | static inline struct iommu_pm_hw_ops *iommu_pm_get_hw_ops_v1(void) |
| 202 | { |
| 203 | return NULL; |
| 204 | } |
| 205 | |
Olav Haugan | 0c2d932 | 2013-01-31 18:35:30 -0800 | [diff] [blame] | 206 | static inline struct iommu_pmon *msm_iommu_pm_alloc(struct device *iommu_dev) |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 207 | { |
| 208 | return NULL; |
| 209 | } |
| 210 | |
| 211 | static inline void msm_iommu_pm_free(struct device *iommu_dev) |
| 212 | { |
| 213 | return; |
| 214 | } |
| 215 | |
Olav Haugan | 0c2d932 | 2013-01-31 18:35:30 -0800 | [diff] [blame] | 216 | static inline int msm_iommu_pm_iommu_register(struct iommu_pmon *info) |
Olav Haugan | 99660ca | 2012-12-04 13:30:41 -0800 | [diff] [blame] | 217 | { |
| 218 | return -EIO; |
| 219 | } |
| 220 | |
| 221 | static inline void msm_iommu_pm_iommu_unregister(struct device *dev) |
| 222 | { |
| 223 | } |
| 224 | |
| 225 | static inline void msm_iommu_attached(struct device *dev) |
| 226 | { |
| 227 | } |
| 228 | |
| 229 | static inline void msm_iommu_detached(struct device *dev) |
| 230 | { |
| 231 | } |
| 232 | #endif |
| 233 | #endif |