icc-bwmon.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  4. * Copyright (C) 2021-2022 Linaro Ltd
  5. * Author: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>, based on
  6. * previous work of Thara Gopinath and msm-4.9 downstream sources.
  7. */
  8. #include <linux/err.h>
  9. #include <linux/interconnect.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/io.h>
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/of.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/pm_opp.h>
  17. #include <linux/regmap.h>
  18. #include <linux/sizes.h>
  19. #define CREATE_TRACE_POINTS
  20. #include "trace_icc-bwmon.h"
  21. /*
  22. * The BWMON samples data throughput within 'sample_ms' time. With three
  23. * configurable thresholds (Low, Medium and High) gives four windows (called
  24. * zones) of current bandwidth:
  25. *
  26. * Zone 0: byte count < THRES_LO
  27. * Zone 1: THRES_LO < byte count < THRES_MED
  28. * Zone 2: THRES_MED < byte count < THRES_HIGH
  29. * Zone 3: THRES_HIGH < byte count
  30. *
  31. * Zones 0 and 2 are not used by this driver.
  32. */
  33. /* Internal sampling clock frequency */
  34. #define HW_TIMER_HZ 19200000
  35. #define BWMON_V4_GLOBAL_IRQ_CLEAR 0x108
  36. #define BWMON_V4_GLOBAL_IRQ_ENABLE 0x10c
  37. /*
  38. * All values here and further are matching regmap fields, so without absolute
  39. * register offsets.
  40. */
  41. #define BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE BIT(0)
  42. /*
  43. * Starting with SDM845, the BWMON4 register space has changed a bit:
  44. * the global registers were jammed into the beginning of the monitor region.
  45. * To keep the proper offsets, one would have to map <GLOBAL_BASE 0x200> and
  46. * <GLOBAL_BASE+0x100 0x300>, which is straight up wrong.
  47. * To facilitate for that, while allowing the older, arguably more proper
  48. * implementations to work, offset the global registers by -0x100 to avoid
  49. * having to map half of the global registers twice.
  50. */
  51. #define BWMON_V4_845_OFFSET 0x100
  52. #define BWMON_V4_GLOBAL_IRQ_CLEAR_845 (BWMON_V4_GLOBAL_IRQ_CLEAR - BWMON_V4_845_OFFSET)
  53. #define BWMON_V4_GLOBAL_IRQ_ENABLE_845 (BWMON_V4_GLOBAL_IRQ_ENABLE - BWMON_V4_845_OFFSET)
  54. #define BWMON_V4_IRQ_STATUS 0x100
  55. #define BWMON_V4_IRQ_CLEAR 0x108
  56. #define BWMON_V4_IRQ_ENABLE 0x10c
  57. #define BWMON_IRQ_ENABLE_MASK (BIT(1) | BIT(3))
  58. #define BWMON_V5_IRQ_STATUS 0x000
  59. #define BWMON_V5_IRQ_CLEAR 0x008
  60. #define BWMON_V5_IRQ_ENABLE 0x00c
  61. #define BWMON_V4_ENABLE 0x2a0
  62. #define BWMON_V5_ENABLE 0x010
  63. #define BWMON_ENABLE_ENABLE BIT(0)
  64. #define BWMON_V4_CLEAR 0x2a4
  65. #define BWMON_V5_CLEAR 0x014
  66. #define BWMON_CLEAR_CLEAR BIT(0)
  67. #define BWMON_CLEAR_CLEAR_ALL BIT(1)
  68. #define BWMON_V4_SAMPLE_WINDOW 0x2a8
  69. #define BWMON_V5_SAMPLE_WINDOW 0x020
  70. #define BWMON_V4_THRESHOLD_HIGH 0x2ac
  71. #define BWMON_V4_THRESHOLD_MED 0x2b0
  72. #define BWMON_V4_THRESHOLD_LOW 0x2b4
  73. #define BWMON_V5_THRESHOLD_HIGH 0x024
  74. #define BWMON_V5_THRESHOLD_MED 0x028
  75. #define BWMON_V5_THRESHOLD_LOW 0x02c
  76. #define BWMON_V4_ZONE_ACTIONS 0x2b8
  77. #define BWMON_V5_ZONE_ACTIONS 0x030
  78. /*
  79. * Actions to perform on some zone 'z' when current zone hits the threshold:
  80. * Increment counter of zone 'z'
  81. */
  82. #define BWMON_ZONE_ACTIONS_INCREMENT(z) (0x2 << ((z) * 2))
  83. /* Clear counter of zone 'z' */
  84. #define BWMON_ZONE_ACTIONS_CLEAR(z) (0x1 << ((z) * 2))
  85. /* Zone 0 threshold hit: Clear zone count */
  86. #define BWMON_ZONE_ACTIONS_ZONE0 (BWMON_ZONE_ACTIONS_CLEAR(0))
  87. /* Zone 1 threshold hit: Increment zone count & clear lower zones */
  88. #define BWMON_ZONE_ACTIONS_ZONE1 (BWMON_ZONE_ACTIONS_INCREMENT(1) | \
  89. BWMON_ZONE_ACTIONS_CLEAR(0))
  90. /* Zone 2 threshold hit: Increment zone count & clear lower zones */
  91. #define BWMON_ZONE_ACTIONS_ZONE2 (BWMON_ZONE_ACTIONS_INCREMENT(2) | \
  92. BWMON_ZONE_ACTIONS_CLEAR(1) | \
  93. BWMON_ZONE_ACTIONS_CLEAR(0))
  94. /* Zone 3 threshold hit: Increment zone count & clear lower zones */
  95. #define BWMON_ZONE_ACTIONS_ZONE3 (BWMON_ZONE_ACTIONS_INCREMENT(3) | \
  96. BWMON_ZONE_ACTIONS_CLEAR(2) | \
  97. BWMON_ZONE_ACTIONS_CLEAR(1) | \
  98. BWMON_ZONE_ACTIONS_CLEAR(0))
  99. /*
  100. * There is no clear documentation/explanation of BWMON_V4_THRESHOLD_COUNT
  101. * register. Based on observations, this is number of times one threshold has to
  102. * be reached, to trigger interrupt in given zone.
  103. *
  104. * 0xff are maximum values meant to ignore the zones 0 and 2.
  105. */
  106. #define BWMON_V4_THRESHOLD_COUNT 0x2bc
  107. #define BWMON_V5_THRESHOLD_COUNT 0x034
  108. #define BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT 0xff
  109. #define BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT 0xff
  110. #define BWMON_V4_ZONE_MAX(zone) (0x2e0 + 4 * (zone))
  111. #define BWMON_V5_ZONE_MAX(zone) (0x044 + 4 * (zone))
  112. /* Quirks for specific BWMON types */
  113. #define BWMON_HAS_GLOBAL_IRQ BIT(0)
  114. #define BWMON_NEEDS_FORCE_CLEAR BIT(1)
  115. enum bwmon_fields {
  116. /* Global region fields, keep them at the top */
  117. F_GLOBAL_IRQ_CLEAR,
  118. F_GLOBAL_IRQ_ENABLE,
  119. F_NUM_GLOBAL_FIELDS,
  120. /* Monitor region fields */
  121. F_IRQ_STATUS = F_NUM_GLOBAL_FIELDS,
  122. F_IRQ_CLEAR,
  123. F_IRQ_ENABLE,
  124. F_ENABLE,
  125. F_CLEAR,
  126. F_SAMPLE_WINDOW,
  127. F_THRESHOLD_HIGH,
  128. F_THRESHOLD_MED,
  129. F_THRESHOLD_LOW,
  130. F_ZONE_ACTIONS_ZONE0,
  131. F_ZONE_ACTIONS_ZONE1,
  132. F_ZONE_ACTIONS_ZONE2,
  133. F_ZONE_ACTIONS_ZONE3,
  134. F_THRESHOLD_COUNT_ZONE0,
  135. F_THRESHOLD_COUNT_ZONE1,
  136. F_THRESHOLD_COUNT_ZONE2,
  137. F_THRESHOLD_COUNT_ZONE3,
  138. F_ZONE0_MAX,
  139. F_ZONE1_MAX,
  140. F_ZONE2_MAX,
  141. F_ZONE3_MAX,
  142. F_NUM_FIELDS
  143. };
  144. struct icc_bwmon_data {
  145. unsigned int sample_ms;
  146. unsigned int count_unit_kb; /* kbytes */
  147. u8 zone1_thres_count;
  148. u8 zone3_thres_count;
  149. unsigned int quirks;
  150. const struct regmap_config *regmap_cfg;
  151. const struct reg_field *regmap_fields;
  152. const struct regmap_config *global_regmap_cfg;
  153. const struct reg_field *global_regmap_fields;
  154. };
  155. struct icc_bwmon {
  156. struct device *dev;
  157. const struct icc_bwmon_data *data;
  158. int irq;
  159. struct regmap_field *regs[F_NUM_FIELDS];
  160. struct regmap_field *global_regs[F_NUM_GLOBAL_FIELDS];
  161. unsigned int max_bw_kbps;
  162. unsigned int min_bw_kbps;
  163. unsigned int target_kbps;
  164. unsigned int current_kbps;
  165. };
  166. /* BWMON v4 */
  167. static const struct reg_field msm8998_bwmon_reg_fields[] = {
  168. [F_GLOBAL_IRQ_CLEAR] = {},
  169. [F_GLOBAL_IRQ_ENABLE] = {},
  170. [F_IRQ_STATUS] = REG_FIELD(BWMON_V4_IRQ_STATUS, 4, 7),
  171. [F_IRQ_CLEAR] = REG_FIELD(BWMON_V4_IRQ_CLEAR, 4, 7),
  172. [F_IRQ_ENABLE] = REG_FIELD(BWMON_V4_IRQ_ENABLE, 4, 7),
  173. /* F_ENABLE covers entire register to disable other features */
  174. [F_ENABLE] = REG_FIELD(BWMON_V4_ENABLE, 0, 31),
  175. [F_CLEAR] = REG_FIELD(BWMON_V4_CLEAR, 0, 1),
  176. [F_SAMPLE_WINDOW] = REG_FIELD(BWMON_V4_SAMPLE_WINDOW, 0, 23),
  177. [F_THRESHOLD_HIGH] = REG_FIELD(BWMON_V4_THRESHOLD_HIGH, 0, 11),
  178. [F_THRESHOLD_MED] = REG_FIELD(BWMON_V4_THRESHOLD_MED, 0, 11),
  179. [F_THRESHOLD_LOW] = REG_FIELD(BWMON_V4_THRESHOLD_LOW, 0, 11),
  180. [F_ZONE_ACTIONS_ZONE0] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 0, 7),
  181. [F_ZONE_ACTIONS_ZONE1] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 8, 15),
  182. [F_ZONE_ACTIONS_ZONE2] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 16, 23),
  183. [F_ZONE_ACTIONS_ZONE3] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 24, 31),
  184. [F_THRESHOLD_COUNT_ZONE0] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 0, 7),
  185. [F_THRESHOLD_COUNT_ZONE1] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 8, 15),
  186. [F_THRESHOLD_COUNT_ZONE2] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 16, 23),
  187. [F_THRESHOLD_COUNT_ZONE3] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 24, 31),
  188. [F_ZONE0_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(0), 0, 11),
  189. [F_ZONE1_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(1), 0, 11),
  190. [F_ZONE2_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(2), 0, 11),
  191. [F_ZONE3_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(3), 0, 11),
  192. };
  193. static const struct regmap_range msm8998_bwmon_reg_noread_ranges[] = {
  194. regmap_reg_range(BWMON_V4_IRQ_CLEAR, BWMON_V4_IRQ_CLEAR),
  195. regmap_reg_range(BWMON_V4_CLEAR, BWMON_V4_CLEAR),
  196. };
  197. static const struct regmap_access_table msm8998_bwmon_reg_read_table = {
  198. .no_ranges = msm8998_bwmon_reg_noread_ranges,
  199. .n_no_ranges = ARRAY_SIZE(msm8998_bwmon_reg_noread_ranges),
  200. };
  201. static const struct regmap_range msm8998_bwmon_reg_volatile_ranges[] = {
  202. regmap_reg_range(BWMON_V4_IRQ_STATUS, BWMON_V4_IRQ_STATUS),
  203. regmap_reg_range(BWMON_V4_ZONE_MAX(0), BWMON_V4_ZONE_MAX(3)),
  204. };
  205. static const struct regmap_access_table msm8998_bwmon_reg_volatile_table = {
  206. .yes_ranges = msm8998_bwmon_reg_volatile_ranges,
  207. .n_yes_ranges = ARRAY_SIZE(msm8998_bwmon_reg_volatile_ranges),
  208. };
  209. static const struct reg_field msm8998_bwmon_global_reg_fields[] = {
  210. [F_GLOBAL_IRQ_CLEAR] = REG_FIELD(BWMON_V4_GLOBAL_IRQ_CLEAR, 0, 0),
  211. [F_GLOBAL_IRQ_ENABLE] = REG_FIELD(BWMON_V4_GLOBAL_IRQ_ENABLE, 0, 0),
  212. };
  213. static const struct regmap_range msm8998_bwmon_global_reg_noread_ranges[] = {
  214. regmap_reg_range(BWMON_V4_GLOBAL_IRQ_CLEAR, BWMON_V4_GLOBAL_IRQ_CLEAR),
  215. };
  216. static const struct regmap_access_table msm8998_bwmon_global_reg_read_table = {
  217. .no_ranges = msm8998_bwmon_global_reg_noread_ranges,
  218. .n_no_ranges = ARRAY_SIZE(msm8998_bwmon_global_reg_noread_ranges),
  219. };
  220. /*
  221. * Fill the cache for non-readable registers only as rest does not really
  222. * matter and can be read from the device.
  223. */
  224. static const struct reg_default msm8998_bwmon_reg_defaults[] = {
  225. { BWMON_V4_IRQ_CLEAR, 0x0 },
  226. { BWMON_V4_CLEAR, 0x0 },
  227. };
  228. static const struct reg_default msm8998_bwmon_global_reg_defaults[] = {
  229. { BWMON_V4_GLOBAL_IRQ_CLEAR, 0x0 },
  230. };
  231. static const struct regmap_config msm8998_bwmon_regmap_cfg = {
  232. .reg_bits = 32,
  233. .reg_stride = 4,
  234. .val_bits = 32,
  235. /*
  236. * No concurrent access expected - driver has one interrupt handler,
  237. * regmap is not shared, no driver or user-space API.
  238. */
  239. .disable_locking = true,
  240. .rd_table = &msm8998_bwmon_reg_read_table,
  241. .volatile_table = &msm8998_bwmon_reg_volatile_table,
  242. .reg_defaults = msm8998_bwmon_reg_defaults,
  243. .num_reg_defaults = ARRAY_SIZE(msm8998_bwmon_reg_defaults),
  244. /*
  245. * Cache is necessary for using regmap fields with non-readable
  246. * registers.
  247. */
  248. .cache_type = REGCACHE_MAPLE,
  249. };
  250. static const struct regmap_config msm8998_bwmon_global_regmap_cfg = {
  251. .reg_bits = 32,
  252. .reg_stride = 4,
  253. .val_bits = 32,
  254. /*
  255. * No concurrent access expected - driver has one interrupt handler,
  256. * regmap is not shared, no driver or user-space API.
  257. */
  258. .disable_locking = true,
  259. .rd_table = &msm8998_bwmon_global_reg_read_table,
  260. .reg_defaults = msm8998_bwmon_global_reg_defaults,
  261. .num_reg_defaults = ARRAY_SIZE(msm8998_bwmon_global_reg_defaults),
  262. /*
  263. * Cache is necessary for using regmap fields with non-readable
  264. * registers.
  265. */
  266. .cache_type = REGCACHE_MAPLE,
  267. };
  268. static const struct reg_field sdm845_cpu_bwmon_reg_fields[] = {
  269. [F_GLOBAL_IRQ_CLEAR] = REG_FIELD(BWMON_V4_GLOBAL_IRQ_CLEAR_845, 0, 0),
  270. [F_GLOBAL_IRQ_ENABLE] = REG_FIELD(BWMON_V4_GLOBAL_IRQ_ENABLE_845, 0, 0),
  271. [F_IRQ_STATUS] = REG_FIELD(BWMON_V4_IRQ_STATUS, 4, 7),
  272. [F_IRQ_CLEAR] = REG_FIELD(BWMON_V4_IRQ_CLEAR, 4, 7),
  273. [F_IRQ_ENABLE] = REG_FIELD(BWMON_V4_IRQ_ENABLE, 4, 7),
  274. /* F_ENABLE covers entire register to disable other features */
  275. [F_ENABLE] = REG_FIELD(BWMON_V4_ENABLE, 0, 31),
  276. [F_CLEAR] = REG_FIELD(BWMON_V4_CLEAR, 0, 1),
  277. [F_SAMPLE_WINDOW] = REG_FIELD(BWMON_V4_SAMPLE_WINDOW, 0, 23),
  278. [F_THRESHOLD_HIGH] = REG_FIELD(BWMON_V4_THRESHOLD_HIGH, 0, 11),
  279. [F_THRESHOLD_MED] = REG_FIELD(BWMON_V4_THRESHOLD_MED, 0, 11),
  280. [F_THRESHOLD_LOW] = REG_FIELD(BWMON_V4_THRESHOLD_LOW, 0, 11),
  281. [F_ZONE_ACTIONS_ZONE0] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 0, 7),
  282. [F_ZONE_ACTIONS_ZONE1] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 8, 15),
  283. [F_ZONE_ACTIONS_ZONE2] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 16, 23),
  284. [F_ZONE_ACTIONS_ZONE3] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 24, 31),
  285. [F_THRESHOLD_COUNT_ZONE0] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 0, 7),
  286. [F_THRESHOLD_COUNT_ZONE1] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 8, 15),
  287. [F_THRESHOLD_COUNT_ZONE2] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 16, 23),
  288. [F_THRESHOLD_COUNT_ZONE3] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 24, 31),
  289. [F_ZONE0_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(0), 0, 11),
  290. [F_ZONE1_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(1), 0, 11),
  291. [F_ZONE2_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(2), 0, 11),
  292. [F_ZONE3_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(3), 0, 11),
  293. };
  294. static const struct regmap_range sdm845_cpu_bwmon_reg_noread_ranges[] = {
  295. regmap_reg_range(BWMON_V4_GLOBAL_IRQ_CLEAR_845, BWMON_V4_GLOBAL_IRQ_CLEAR_845),
  296. regmap_reg_range(BWMON_V4_IRQ_CLEAR, BWMON_V4_IRQ_CLEAR),
  297. regmap_reg_range(BWMON_V4_CLEAR, BWMON_V4_CLEAR),
  298. };
  299. static const struct regmap_access_table sdm845_cpu_bwmon_reg_read_table = {
  300. .no_ranges = sdm845_cpu_bwmon_reg_noread_ranges,
  301. .n_no_ranges = ARRAY_SIZE(sdm845_cpu_bwmon_reg_noread_ranges),
  302. };
  303. /*
  304. * Fill the cache for non-readable registers only as rest does not really
  305. * matter and can be read from the device.
  306. */
  307. static const struct reg_default sdm845_cpu_bwmon_reg_defaults[] = {
  308. { BWMON_V4_GLOBAL_IRQ_CLEAR_845, 0x0 },
  309. { BWMON_V4_IRQ_CLEAR, 0x0 },
  310. { BWMON_V4_CLEAR, 0x0 },
  311. };
  312. static const struct regmap_config sdm845_cpu_bwmon_regmap_cfg = {
  313. .reg_bits = 32,
  314. .reg_stride = 4,
  315. .val_bits = 32,
  316. /*
  317. * No concurrent access expected - driver has one interrupt handler,
  318. * regmap is not shared, no driver or user-space API.
  319. */
  320. .disable_locking = true,
  321. .rd_table = &sdm845_cpu_bwmon_reg_read_table,
  322. .volatile_table = &msm8998_bwmon_reg_volatile_table,
  323. .reg_defaults = sdm845_cpu_bwmon_reg_defaults,
  324. .num_reg_defaults = ARRAY_SIZE(sdm845_cpu_bwmon_reg_defaults),
  325. /*
  326. * Cache is necessary for using regmap fields with non-readable
  327. * registers.
  328. */
  329. .cache_type = REGCACHE_MAPLE,
  330. };
  331. /* BWMON v5 */
  332. static const struct reg_field sdm845_llcc_bwmon_reg_fields[] = {
  333. [F_GLOBAL_IRQ_CLEAR] = {},
  334. [F_GLOBAL_IRQ_ENABLE] = {},
  335. [F_IRQ_STATUS] = REG_FIELD(BWMON_V5_IRQ_STATUS, 0, 3),
  336. [F_IRQ_CLEAR] = REG_FIELD(BWMON_V5_IRQ_CLEAR, 0, 3),
  337. [F_IRQ_ENABLE] = REG_FIELD(BWMON_V5_IRQ_ENABLE, 0, 3),
  338. /* F_ENABLE covers entire register to disable other features */
  339. [F_ENABLE] = REG_FIELD(BWMON_V5_ENABLE, 0, 31),
  340. [F_CLEAR] = REG_FIELD(BWMON_V5_CLEAR, 0, 1),
  341. [F_SAMPLE_WINDOW] = REG_FIELD(BWMON_V5_SAMPLE_WINDOW, 0, 19),
  342. [F_THRESHOLD_HIGH] = REG_FIELD(BWMON_V5_THRESHOLD_HIGH, 0, 11),
  343. [F_THRESHOLD_MED] = REG_FIELD(BWMON_V5_THRESHOLD_MED, 0, 11),
  344. [F_THRESHOLD_LOW] = REG_FIELD(BWMON_V5_THRESHOLD_LOW, 0, 11),
  345. [F_ZONE_ACTIONS_ZONE0] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 0, 7),
  346. [F_ZONE_ACTIONS_ZONE1] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 8, 15),
  347. [F_ZONE_ACTIONS_ZONE2] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 16, 23),
  348. [F_ZONE_ACTIONS_ZONE3] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 24, 31),
  349. [F_THRESHOLD_COUNT_ZONE0] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 0, 7),
  350. [F_THRESHOLD_COUNT_ZONE1] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 8, 15),
  351. [F_THRESHOLD_COUNT_ZONE2] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 16, 23),
  352. [F_THRESHOLD_COUNT_ZONE3] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 24, 31),
  353. [F_ZONE0_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(0), 0, 11),
  354. [F_ZONE1_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(1), 0, 11),
  355. [F_ZONE2_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(2), 0, 11),
  356. [F_ZONE3_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(3), 0, 11),
  357. };
  358. static const struct regmap_range sdm845_llcc_bwmon_reg_noread_ranges[] = {
  359. regmap_reg_range(BWMON_V5_IRQ_CLEAR, BWMON_V5_IRQ_CLEAR),
  360. regmap_reg_range(BWMON_V5_CLEAR, BWMON_V5_CLEAR),
  361. };
  362. static const struct regmap_access_table sdm845_llcc_bwmon_reg_read_table = {
  363. .no_ranges = sdm845_llcc_bwmon_reg_noread_ranges,
  364. .n_no_ranges = ARRAY_SIZE(sdm845_llcc_bwmon_reg_noread_ranges),
  365. };
  366. static const struct regmap_range sdm845_llcc_bwmon_reg_volatile_ranges[] = {
  367. regmap_reg_range(BWMON_V5_IRQ_STATUS, BWMON_V5_IRQ_STATUS),
  368. regmap_reg_range(BWMON_V5_ZONE_MAX(0), BWMON_V5_ZONE_MAX(3)),
  369. };
  370. static const struct regmap_access_table sdm845_llcc_bwmon_reg_volatile_table = {
  371. .yes_ranges = sdm845_llcc_bwmon_reg_volatile_ranges,
  372. .n_yes_ranges = ARRAY_SIZE(sdm845_llcc_bwmon_reg_volatile_ranges),
  373. };
  374. /*
  375. * Fill the cache for non-readable registers only as rest does not really
  376. * matter and can be read from the device.
  377. */
  378. static const struct reg_default sdm845_llcc_bwmon_reg_defaults[] = {
  379. { BWMON_V5_IRQ_CLEAR, 0x0 },
  380. { BWMON_V5_CLEAR, 0x0 },
  381. };
  382. static const struct regmap_config sdm845_llcc_bwmon_regmap_cfg = {
  383. .reg_bits = 32,
  384. .reg_stride = 4,
  385. .val_bits = 32,
  386. /*
  387. * No concurrent access expected - driver has one interrupt handler,
  388. * regmap is not shared, no driver or user-space API.
  389. */
  390. .disable_locking = true,
  391. .rd_table = &sdm845_llcc_bwmon_reg_read_table,
  392. .volatile_table = &sdm845_llcc_bwmon_reg_volatile_table,
  393. .reg_defaults = sdm845_llcc_bwmon_reg_defaults,
  394. .num_reg_defaults = ARRAY_SIZE(sdm845_llcc_bwmon_reg_defaults),
  395. /*
  396. * Cache is necessary for using regmap fields with non-readable
  397. * registers.
  398. */
  399. .cache_type = REGCACHE_MAPLE,
  400. };
  401. static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all)
  402. {
  403. unsigned int val = BWMON_CLEAR_CLEAR;
  404. if (clear_all)
  405. val |= BWMON_CLEAR_CLEAR_ALL;
  406. /*
  407. * Clear counters. The order and barriers are
  408. * important. Quoting downstream Qualcomm msm-4.9 tree:
  409. *
  410. * The counter clear and IRQ clear bits are not in the same 4KB
  411. * region. So, we need to make sure the counter clear is completed
  412. * before we try to clear the IRQ or do any other counter operations.
  413. */
  414. regmap_field_force_write(bwmon->regs[F_CLEAR], val);
  415. if (bwmon->data->quirks & BWMON_NEEDS_FORCE_CLEAR)
  416. regmap_field_force_write(bwmon->regs[F_CLEAR], 0);
  417. }
  418. static void bwmon_clear_irq(struct icc_bwmon *bwmon)
  419. {
  420. struct regmap_field *global_irq_clr;
  421. if (bwmon->data->global_regmap_fields)
  422. global_irq_clr = bwmon->global_regs[F_GLOBAL_IRQ_CLEAR];
  423. else
  424. global_irq_clr = bwmon->regs[F_GLOBAL_IRQ_CLEAR];
  425. /*
  426. * Clear zone and global interrupts. The order and barriers are
  427. * important. Quoting downstream Qualcomm msm-4.9 tree:
  428. *
  429. * Synchronize the local interrupt clear in mon_irq_clear()
  430. * with the global interrupt clear here. Otherwise, the CPU
  431. * may reorder the two writes and clear the global interrupt
  432. * before the local interrupt, causing the global interrupt
  433. * to be retriggered by the local interrupt still being high.
  434. *
  435. * Similarly, because the global registers are in a different
  436. * region than the local registers, we need to ensure any register
  437. * writes to enable the monitor after this call are ordered with the
  438. * clearing here so that local writes don't happen before the
  439. * interrupt is cleared.
  440. */
  441. regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], BWMON_IRQ_ENABLE_MASK);
  442. if (bwmon->data->quirks & BWMON_NEEDS_FORCE_CLEAR)
  443. regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], 0);
  444. if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
  445. regmap_field_force_write(global_irq_clr,
  446. BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
  447. }
  448. static void bwmon_disable(struct icc_bwmon *bwmon)
  449. {
  450. struct regmap_field *global_irq_en;
  451. if (bwmon->data->global_regmap_fields)
  452. global_irq_en = bwmon->global_regs[F_GLOBAL_IRQ_ENABLE];
  453. else
  454. global_irq_en = bwmon->regs[F_GLOBAL_IRQ_ENABLE];
  455. /* Disable interrupts. Strict ordering, see bwmon_clear_irq(). */
  456. if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
  457. regmap_field_write(global_irq_en, 0x0);
  458. regmap_field_write(bwmon->regs[F_IRQ_ENABLE], 0x0);
  459. /*
  460. * Disable bwmon. Must happen before bwmon_clear_irq() to avoid spurious
  461. * IRQ.
  462. */
  463. regmap_field_write(bwmon->regs[F_ENABLE], 0x0);
  464. }
  465. static void bwmon_enable(struct icc_bwmon *bwmon, unsigned int irq_enable)
  466. {
  467. struct regmap_field *global_irq_en;
  468. if (bwmon->data->global_regmap_fields)
  469. global_irq_en = bwmon->global_regs[F_GLOBAL_IRQ_ENABLE];
  470. else
  471. global_irq_en = bwmon->regs[F_GLOBAL_IRQ_ENABLE];
  472. /* Enable interrupts */
  473. if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
  474. regmap_field_write(global_irq_en,
  475. BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
  476. regmap_field_write(bwmon->regs[F_IRQ_ENABLE], irq_enable);
  477. /* Enable bwmon */
  478. regmap_field_write(bwmon->regs[F_ENABLE], BWMON_ENABLE_ENABLE);
  479. }
  480. static unsigned int bwmon_kbps_to_count(struct icc_bwmon *bwmon,
  481. unsigned int kbps)
  482. {
  483. return kbps / bwmon->data->count_unit_kb;
  484. }
  485. static void bwmon_set_threshold(struct icc_bwmon *bwmon,
  486. struct regmap_field *reg, unsigned int kbps)
  487. {
  488. unsigned int thres;
  489. thres = mult_frac(bwmon_kbps_to_count(bwmon, kbps),
  490. bwmon->data->sample_ms, MSEC_PER_SEC);
  491. regmap_field_write(reg, thres);
  492. }
  493. static void bwmon_start(struct icc_bwmon *bwmon)
  494. {
  495. const struct icc_bwmon_data *data = bwmon->data;
  496. u32 bw_low = 0;
  497. int window;
  498. /* No need to check for errors, as this must have succeeded before. */
  499. dev_pm_opp_put(dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_low, 0));
  500. bwmon_clear_counters(bwmon, true);
  501. window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
  502. /* Maximum sampling window: 0xffffff for v4 and 0xfffff for v5 */
  503. regmap_field_write(bwmon->regs[F_SAMPLE_WINDOW], window);
  504. bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH], bw_low);
  505. bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_MED], bw_low);
  506. bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_LOW], 0);
  507. regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE0],
  508. BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT);
  509. regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE1],
  510. data->zone1_thres_count);
  511. regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE2],
  512. BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT);
  513. regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE3],
  514. data->zone3_thres_count);
  515. regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE0],
  516. BWMON_ZONE_ACTIONS_ZONE0);
  517. regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE1],
  518. BWMON_ZONE_ACTIONS_ZONE1);
  519. regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE2],
  520. BWMON_ZONE_ACTIONS_ZONE2);
  521. regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE3],
  522. BWMON_ZONE_ACTIONS_ZONE3);
  523. bwmon_clear_irq(bwmon);
  524. bwmon_enable(bwmon, BWMON_IRQ_ENABLE_MASK);
  525. }
  526. static irqreturn_t bwmon_intr(int irq, void *dev_id)
  527. {
  528. struct icc_bwmon *bwmon = dev_id;
  529. unsigned int status, max;
  530. int zone;
  531. if (regmap_field_read(bwmon->regs[F_IRQ_STATUS], &status))
  532. return IRQ_NONE;
  533. status &= BWMON_IRQ_ENABLE_MASK;
  534. if (!status) {
  535. /*
  536. * Only zone 1 and zone 3 interrupts are enabled but zone 2
  537. * threshold could be hit and trigger interrupt even if not
  538. * enabled.
  539. * Such spurious interrupt might come with valuable max count or
  540. * not, so solution would be to always check all
  541. * BWMON_ZONE_MAX() registers to find the highest value.
  542. * Such case is currently ignored.
  543. */
  544. return IRQ_NONE;
  545. }
  546. bwmon_disable(bwmon);
  547. zone = get_bitmask_order(status) - 1;
  548. /*
  549. * Zone max bytes count register returns count units within sampling
  550. * window. Downstream kernel for BWMONv4 (called BWMON type 2 in
  551. * downstream) always increments the max bytes count by one.
  552. */
  553. if (regmap_field_read(bwmon->regs[F_ZONE0_MAX + zone], &max))
  554. return IRQ_NONE;
  555. max += 1;
  556. max *= bwmon->data->count_unit_kb;
  557. bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->data->sample_ms);
  558. return IRQ_WAKE_THREAD;
  559. }
  560. static irqreturn_t bwmon_intr_thread(int irq, void *dev_id)
  561. {
  562. struct icc_bwmon *bwmon = dev_id;
  563. unsigned int irq_enable = 0;
  564. struct dev_pm_opp *opp, *target_opp;
  565. unsigned int bw_kbps, up_kbps, down_kbps, meas_kbps;
  566. bw_kbps = bwmon->target_kbps;
  567. meas_kbps = bwmon->target_kbps;
  568. target_opp = dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_kbps, 0);
  569. if (IS_ERR(target_opp) && PTR_ERR(target_opp) == -ERANGE)
  570. target_opp = dev_pm_opp_find_bw_floor(bwmon->dev, &bw_kbps, 0);
  571. bwmon->target_kbps = bw_kbps;
  572. bw_kbps--;
  573. opp = dev_pm_opp_find_bw_floor(bwmon->dev, &bw_kbps, 0);
  574. if (IS_ERR(opp) && PTR_ERR(opp) == -ERANGE)
  575. down_kbps = bwmon->target_kbps;
  576. else
  577. down_kbps = bw_kbps;
  578. up_kbps = bwmon->target_kbps + 1;
  579. if (bwmon->target_kbps >= bwmon->max_bw_kbps)
  580. irq_enable = BIT(1);
  581. else if (bwmon->target_kbps <= bwmon->min_bw_kbps)
  582. irq_enable = BIT(3);
  583. else
  584. irq_enable = BWMON_IRQ_ENABLE_MASK;
  585. bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH],
  586. up_kbps);
  587. bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_MED],
  588. down_kbps);
  589. bwmon_clear_counters(bwmon, false);
  590. bwmon_clear_irq(bwmon);
  591. bwmon_enable(bwmon, irq_enable);
  592. trace_qcom_bwmon_update(dev_name(bwmon->dev), meas_kbps, up_kbps, down_kbps);
  593. if (bwmon->target_kbps == bwmon->current_kbps)
  594. goto out;
  595. dev_pm_opp_set_opp(bwmon->dev, target_opp);
  596. bwmon->current_kbps = bwmon->target_kbps;
  597. out:
  598. dev_pm_opp_put(target_opp);
  599. if (!IS_ERR(opp))
  600. dev_pm_opp_put(opp);
  601. return IRQ_HANDLED;
  602. }
  603. static int bwmon_init_regmap(struct platform_device *pdev,
  604. struct icc_bwmon *bwmon)
  605. {
  606. struct device *dev = &pdev->dev;
  607. void __iomem *base;
  608. struct regmap *map;
  609. int ret;
  610. /* Map the monitor base */
  611. base = devm_platform_ioremap_resource(pdev, 0);
  612. if (IS_ERR(base))
  613. return dev_err_probe(dev, PTR_ERR(base),
  614. "failed to map bwmon registers\n");
  615. map = devm_regmap_init_mmio(dev, base, bwmon->data->regmap_cfg);
  616. if (IS_ERR(map))
  617. return dev_err_probe(dev, PTR_ERR(map),
  618. "failed to initialize regmap\n");
  619. BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_global_reg_fields) != F_NUM_GLOBAL_FIELDS);
  620. BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_reg_fields) != F_NUM_FIELDS);
  621. BUILD_BUG_ON(ARRAY_SIZE(sdm845_cpu_bwmon_reg_fields) != F_NUM_FIELDS);
  622. BUILD_BUG_ON(ARRAY_SIZE(sdm845_llcc_bwmon_reg_fields) != F_NUM_FIELDS);
  623. ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->regs,
  624. bwmon->data->regmap_fields,
  625. F_NUM_FIELDS);
  626. if (ret)
  627. return ret;
  628. if (bwmon->data->global_regmap_cfg) {
  629. /* Map the global base, if separate */
  630. base = devm_platform_ioremap_resource(pdev, 1);
  631. if (IS_ERR(base))
  632. return dev_err_probe(dev, PTR_ERR(base),
  633. "failed to map bwmon global registers\n");
  634. map = devm_regmap_init_mmio(dev, base, bwmon->data->global_regmap_cfg);
  635. if (IS_ERR(map))
  636. return dev_err_probe(dev, PTR_ERR(map),
  637. "failed to initialize global regmap\n");
  638. ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->global_regs,
  639. bwmon->data->global_regmap_fields,
  640. F_NUM_GLOBAL_FIELDS);
  641. }
  642. return ret;
  643. }
  644. static int bwmon_probe(struct platform_device *pdev)
  645. {
  646. struct device *dev = &pdev->dev;
  647. struct dev_pm_opp *opp;
  648. struct icc_bwmon *bwmon;
  649. int ret;
  650. bwmon = devm_kzalloc(dev, sizeof(*bwmon), GFP_KERNEL);
  651. if (!bwmon)
  652. return -ENOMEM;
  653. bwmon->data = of_device_get_match_data(dev);
  654. ret = bwmon_init_regmap(pdev, bwmon);
  655. if (ret)
  656. return ret;
  657. bwmon->irq = platform_get_irq(pdev, 0);
  658. if (bwmon->irq < 0)
  659. return bwmon->irq;
  660. ret = devm_pm_opp_of_add_table(dev);
  661. if (ret)
  662. return dev_err_probe(dev, ret, "failed to add OPP table\n");
  663. bwmon->max_bw_kbps = UINT_MAX;
  664. opp = dev_pm_opp_find_bw_floor(dev, &bwmon->max_bw_kbps, 0);
  665. if (IS_ERR(opp))
  666. return dev_err_probe(dev, PTR_ERR(opp), "failed to find max peak bandwidth\n");
  667. dev_pm_opp_put(opp);
  668. bwmon->min_bw_kbps = 0;
  669. opp = dev_pm_opp_find_bw_ceil(dev, &bwmon->min_bw_kbps, 0);
  670. if (IS_ERR(opp))
  671. return dev_err_probe(dev, PTR_ERR(opp), "failed to find min peak bandwidth\n");
  672. dev_pm_opp_put(opp);
  673. bwmon->dev = dev;
  674. bwmon_disable(bwmon);
  675. /*
  676. * SoCs with multiple cpu-bwmon instances can end up using a shared interrupt
  677. * line. Using the devm_ variant might result in the IRQ handler being executed
  678. * after bwmon_disable in bwmon_remove()
  679. */
  680. ret = request_threaded_irq(bwmon->irq, bwmon_intr, bwmon_intr_thread,
  681. IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), bwmon);
  682. if (ret)
  683. return dev_err_probe(dev, ret, "failed to request IRQ\n");
  684. platform_set_drvdata(pdev, bwmon);
  685. bwmon_start(bwmon);
  686. return 0;
  687. }
  688. static void bwmon_remove(struct platform_device *pdev)
  689. {
  690. struct icc_bwmon *bwmon = platform_get_drvdata(pdev);
  691. bwmon_disable(bwmon);
  692. free_irq(bwmon->irq, bwmon);
  693. }
  694. static const struct icc_bwmon_data msm8998_bwmon_data = {
  695. .sample_ms = 4,
  696. .count_unit_kb = 1024,
  697. .zone1_thres_count = 16,
  698. .zone3_thres_count = 1,
  699. .quirks = BWMON_HAS_GLOBAL_IRQ,
  700. .regmap_fields = msm8998_bwmon_reg_fields,
  701. .regmap_cfg = &msm8998_bwmon_regmap_cfg,
  702. .global_regmap_fields = msm8998_bwmon_global_reg_fields,
  703. .global_regmap_cfg = &msm8998_bwmon_global_regmap_cfg,
  704. };
  705. static const struct icc_bwmon_data sdm845_cpu_bwmon_data = {
  706. .sample_ms = 4,
  707. .count_unit_kb = 64,
  708. .zone1_thres_count = 16,
  709. .zone3_thres_count = 1,
  710. .quirks = BWMON_HAS_GLOBAL_IRQ,
  711. .regmap_fields = sdm845_cpu_bwmon_reg_fields,
  712. .regmap_cfg = &sdm845_cpu_bwmon_regmap_cfg,
  713. };
  714. static const struct icc_bwmon_data sdm845_llcc_bwmon_data = {
  715. .sample_ms = 4,
  716. .count_unit_kb = 1024,
  717. .zone1_thres_count = 16,
  718. .zone3_thres_count = 1,
  719. .regmap_fields = sdm845_llcc_bwmon_reg_fields,
  720. .regmap_cfg = &sdm845_llcc_bwmon_regmap_cfg,
  721. };
  722. static const struct icc_bwmon_data sc7280_llcc_bwmon_data = {
  723. .sample_ms = 4,
  724. .count_unit_kb = 64,
  725. .zone1_thres_count = 16,
  726. .zone3_thres_count = 1,
  727. .quirks = BWMON_NEEDS_FORCE_CLEAR,
  728. .regmap_fields = sdm845_llcc_bwmon_reg_fields,
  729. .regmap_cfg = &sdm845_llcc_bwmon_regmap_cfg,
  730. };
  731. static const struct of_device_id bwmon_of_match[] = {
  732. /* BWMONv4, separate monitor and global register spaces */
  733. { .compatible = "qcom,msm8998-bwmon", .data = &msm8998_bwmon_data },
  734. /* BWMONv4, unified register space */
  735. { .compatible = "qcom,sdm845-bwmon", .data = &sdm845_cpu_bwmon_data },
  736. /* BWMONv5 */
  737. { .compatible = "qcom,sdm845-llcc-bwmon", .data = &sdm845_llcc_bwmon_data },
  738. { .compatible = "qcom,sc7280-llcc-bwmon", .data = &sc7280_llcc_bwmon_data },
  739. /* Compatibles kept for legacy reasons */
  740. { .compatible = "qcom,sc7280-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
  741. { .compatible = "qcom,sc8280xp-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
  742. { .compatible = "qcom,sm8550-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
  743. {}
  744. };
  745. MODULE_DEVICE_TABLE(of, bwmon_of_match);
  746. static struct platform_driver bwmon_driver = {
  747. .probe = bwmon_probe,
  748. .remove_new = bwmon_remove,
  749. .driver = {
  750. .name = "qcom-bwmon",
  751. .of_match_table = bwmon_of_match,
  752. },
  753. };
  754. module_platform_driver(bwmon_driver);
  755. MODULE_AUTHOR("Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>");
  756. MODULE_DESCRIPTION("QCOM BWMON driver");
  757. MODULE_LICENSE("GPL");