mlx-platform.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288
  1. /*
  2. * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
  3. * Copyright (c) 2016 Vadim Pasternak <vadimp@mellanox.com>
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the names of the copyright holders nor the names of its
  14. * contributors may be used to endorse or promote products derived from
  15. * this software without specific prior written permission.
  16. *
  17. * Alternatively, this software may be distributed under the terms of the
  18. * GNU General Public License ("GPL") version 2 as published by the Free
  19. * Software Foundation.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  22. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  25. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  26. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  27. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  30. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  31. * POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. #include <linux/device.h>
  34. #include <linux/dmi.h>
  35. #include <linux/i2c.h>
  36. #include <linux/i2c-mux.h>
  37. #include <linux/io.h>
  38. #include <linux/module.h>
  39. #include <linux/platform_device.h>
  40. #include <linux/platform_data/i2c-mux-reg.h>
  41. #include <linux/platform_data/mlxreg.h>
  42. #include <linux/regmap.h>
  43. #define MLX_PLAT_DEVICE_NAME "mlxplat"
  44. /* LPC bus IO offsets */
  45. #define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000
  46. #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500
  47. #define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20
  48. #define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21
  49. #define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22
  50. #define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET 0x23
  51. #define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET 0x24
  52. #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a
  53. #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b
  54. #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40
  55. #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41
  56. #define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET 0x58
  57. #define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET 0x59
  58. #define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET 0x5a
  59. #define MLXPLAT_CPLD_LPC_REG_PWR_OFFSET 0x64
  60. #define MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET 0x65
  61. #define MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET 0x66
  62. #define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88
  63. #define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89
  64. #define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a
  65. #define MLXPLAT_CPLD_LPC_IO_RANGE 0x100
  66. #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb
  67. #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda
  68. #define MLXPLAT_CPLD_LPC_PIO_OFFSET 0x10000UL
  69. #define MLXPLAT_CPLD_LPC_REG1 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
  70. MLXPLAT_CPLD_LPC_I2C_CH1_OFF) | \
  71. MLXPLAT_CPLD_LPC_PIO_OFFSET)
  72. #define MLXPLAT_CPLD_LPC_REG2 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
  73. MLXPLAT_CPLD_LPC_I2C_CH2_OFF) | \
  74. MLXPLAT_CPLD_LPC_PIO_OFFSET)
  75. /* Masks for aggregation, psu, pwr and fan event in CPLD related registers. */
  76. #define MLXPLAT_CPLD_AGGR_PSU_MASK_DEF 0x08
  77. #define MLXPLAT_CPLD_AGGR_PWR_MASK_DEF 0x08
  78. #define MLXPLAT_CPLD_AGGR_FAN_MASK_DEF 0x40
  79. #define MLXPLAT_CPLD_AGGR_MASK_DEF (MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \
  80. MLXPLAT_CPLD_AGGR_FAN_MASK_DEF)
  81. #define MLXPLAT_CPLD_AGGR_MASK_NG_DEF 0x04
  82. #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc0
  83. #define MLXPLAT_CPLD_AGGR_MASK_MSN21XX 0x04
  84. #define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0)
  85. #define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0)
  86. #define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0)
  87. #define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0)
  88. #define MLXPLAT_CPLD_LED_LO_NIBBLE_MASK GENMASK(7, 4)
  89. #define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 0)
  90. /* Default I2C parent bus number */
  91. #define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1
  92. /* Maximum number of possible physical buses equipped on system */
  93. #define MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM 16
  94. /* Number of channels in group */
  95. #define MLXPLAT_CPLD_GRP_CHNL_NUM 8
  96. /* Start channel numbers */
  97. #define MLXPLAT_CPLD_CH1 2
  98. #define MLXPLAT_CPLD_CH2 10
  99. /* Number of LPC attached MUX platform devices */
  100. #define MLXPLAT_CPLD_LPC_MUX_DEVS 2
  101. /* Hotplug devices adapter numbers */
  102. #define MLXPLAT_CPLD_NR_NONE -1
  103. #define MLXPLAT_CPLD_PSU_DEFAULT_NR 10
  104. #define MLXPLAT_CPLD_PSU_MSNXXXX_NR 4
  105. #define MLXPLAT_CPLD_FAN1_DEFAULT_NR 11
  106. #define MLXPLAT_CPLD_FAN2_DEFAULT_NR 12
  107. #define MLXPLAT_CPLD_FAN3_DEFAULT_NR 13
  108. #define MLXPLAT_CPLD_FAN4_DEFAULT_NR 14
  109. /* mlxplat_priv - platform private data
  110. * @pdev_i2c - i2c controller platform device
  111. * @pdev_mux - array of mux platform devices
  112. * @pdev_hotplug - hotplug platform devices
  113. * @pdev_led - led platform devices
  114. */
  115. struct mlxplat_priv {
  116. struct platform_device *pdev_i2c;
  117. struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS];
  118. struct platform_device *pdev_hotplug;
  119. struct platform_device *pdev_led;
  120. };
  121. /* Regions for LPC I2C controller and LPC base register space */
  122. static const struct resource mlxplat_lpc_resources[] = {
  123. [0] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_I2C_BASE_ADRR,
  124. MLXPLAT_CPLD_LPC_IO_RANGE,
  125. "mlxplat_cpld_lpc_i2c_ctrl", IORESOURCE_IO),
  126. [1] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_REG_BASE_ADRR,
  127. MLXPLAT_CPLD_LPC_IO_RANGE,
  128. "mlxplat_cpld_lpc_regs",
  129. IORESOURCE_IO),
  130. };
  131. /* Platform default channels */
  132. static const int mlxplat_default_channels[][MLXPLAT_CPLD_GRP_CHNL_NUM] = {
  133. {
  134. MLXPLAT_CPLD_CH1, MLXPLAT_CPLD_CH1 + 1, MLXPLAT_CPLD_CH1 + 2,
  135. MLXPLAT_CPLD_CH1 + 3, MLXPLAT_CPLD_CH1 + 4, MLXPLAT_CPLD_CH1 +
  136. 5, MLXPLAT_CPLD_CH1 + 6, MLXPLAT_CPLD_CH1 + 7
  137. },
  138. {
  139. MLXPLAT_CPLD_CH2, MLXPLAT_CPLD_CH2 + 1, MLXPLAT_CPLD_CH2 + 2,
  140. MLXPLAT_CPLD_CH2 + 3, MLXPLAT_CPLD_CH2 + 4, MLXPLAT_CPLD_CH2 +
  141. 5, MLXPLAT_CPLD_CH2 + 6, MLXPLAT_CPLD_CH2 + 7
  142. },
  143. };
  144. /* Platform channels for MSN21xx system family */
  145. static const int mlxplat_msn21xx_channels[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  146. /* Platform mux data */
  147. static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = {
  148. {
  149. .parent = 1,
  150. .base_nr = MLXPLAT_CPLD_CH1,
  151. .write_only = 1,
  152. .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1,
  153. .reg_size = 1,
  154. .idle_in_use = 1,
  155. },
  156. {
  157. .parent = 1,
  158. .base_nr = MLXPLAT_CPLD_CH2,
  159. .write_only = 1,
  160. .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2,
  161. .reg_size = 1,
  162. .idle_in_use = 1,
  163. },
  164. };
  165. /* Platform hotplug devices */
  166. static struct i2c_board_info mlxplat_mlxcpld_psu[] = {
  167. {
  168. I2C_BOARD_INFO("24c02", 0x51),
  169. },
  170. {
  171. I2C_BOARD_INFO("24c02", 0x50),
  172. },
  173. };
  174. static struct i2c_board_info mlxplat_mlxcpld_ng_psu[] = {
  175. {
  176. I2C_BOARD_INFO("24c32", 0x51),
  177. },
  178. {
  179. I2C_BOARD_INFO("24c32", 0x50),
  180. },
  181. };
  182. static struct i2c_board_info mlxplat_mlxcpld_pwr[] = {
  183. {
  184. I2C_BOARD_INFO("dps460", 0x59),
  185. },
  186. {
  187. I2C_BOARD_INFO("dps460", 0x58),
  188. },
  189. };
  190. static struct i2c_board_info mlxplat_mlxcpld_fan[] = {
  191. {
  192. I2C_BOARD_INFO("24c32", 0x50),
  193. },
  194. {
  195. I2C_BOARD_INFO("24c32", 0x50),
  196. },
  197. {
  198. I2C_BOARD_INFO("24c32", 0x50),
  199. },
  200. {
  201. I2C_BOARD_INFO("24c32", 0x50),
  202. },
  203. };
  204. /* Platform hotplug default data */
  205. static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = {
  206. {
  207. .label = "psu1",
  208. .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
  209. .mask = BIT(0),
  210. .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0],
  211. .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
  212. },
  213. {
  214. .label = "psu2",
  215. .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
  216. .mask = BIT(1),
  217. .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1],
  218. .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
  219. },
  220. };
  221. static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_items_data[] = {
  222. {
  223. .label = "pwr1",
  224. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  225. .mask = BIT(0),
  226. .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0],
  227. .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
  228. },
  229. {
  230. .label = "pwr2",
  231. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  232. .mask = BIT(1),
  233. .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1],
  234. .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
  235. },
  236. };
  237. static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = {
  238. {
  239. .label = "fan1",
  240. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  241. .mask = BIT(0),
  242. .hpdev.brdinfo = &mlxplat_mlxcpld_fan[0],
  243. .hpdev.nr = MLXPLAT_CPLD_FAN1_DEFAULT_NR,
  244. },
  245. {
  246. .label = "fan2",
  247. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  248. .mask = BIT(1),
  249. .hpdev.brdinfo = &mlxplat_mlxcpld_fan[1],
  250. .hpdev.nr = MLXPLAT_CPLD_FAN2_DEFAULT_NR,
  251. },
  252. {
  253. .label = "fan3",
  254. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  255. .mask = BIT(2),
  256. .hpdev.brdinfo = &mlxplat_mlxcpld_fan[2],
  257. .hpdev.nr = MLXPLAT_CPLD_FAN3_DEFAULT_NR,
  258. },
  259. {
  260. .label = "fan4",
  261. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  262. .mask = BIT(3),
  263. .hpdev.brdinfo = &mlxplat_mlxcpld_fan[3],
  264. .hpdev.nr = MLXPLAT_CPLD_FAN4_DEFAULT_NR,
  265. },
  266. };
  267. static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = {
  268. {
  269. .data = mlxplat_mlxcpld_default_psu_items_data,
  270. .aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF,
  271. .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
  272. .mask = MLXPLAT_CPLD_PSU_MASK,
  273. .count = ARRAY_SIZE(mlxplat_mlxcpld_psu),
  274. .inversed = 1,
  275. .health = false,
  276. },
  277. {
  278. .data = mlxplat_mlxcpld_default_pwr_items_data,
  279. .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
  280. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  281. .mask = MLXPLAT_CPLD_PWR_MASK,
  282. .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
  283. .inversed = 0,
  284. .health = false,
  285. },
  286. {
  287. .data = mlxplat_mlxcpld_default_fan_items_data,
  288. .aggr_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF,
  289. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  290. .mask = MLXPLAT_CPLD_FAN_MASK,
  291. .count = ARRAY_SIZE(mlxplat_mlxcpld_fan),
  292. .inversed = 1,
  293. .health = false,
  294. },
  295. };
  296. static
  297. struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = {
  298. .items = mlxplat_mlxcpld_default_items,
  299. .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items),
  300. .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
  301. .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
  302. };
  303. static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_pwr_items_data[] = {
  304. {
  305. .label = "pwr1",
  306. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  307. .mask = BIT(0),
  308. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  309. },
  310. {
  311. .label = "pwr2",
  312. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  313. .mask = BIT(1),
  314. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  315. },
  316. };
  317. /* Platform hotplug MSN21xx system family data */
  318. static struct mlxreg_core_item mlxplat_mlxcpld_msn21xx_items[] = {
  319. {
  320. .data = mlxplat_mlxcpld_msn21xx_pwr_items_data,
  321. .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
  322. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  323. .mask = MLXPLAT_CPLD_PWR_MASK,
  324. .count = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_pwr_items_data),
  325. .inversed = 0,
  326. .health = false,
  327. },
  328. };
  329. static
  330. struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = {
  331. .items = mlxplat_mlxcpld_msn21xx_items,
  332. .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_items),
  333. .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
  334. .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
  335. .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
  336. .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
  337. };
  338. /* Platform hotplug msn274x system family data */
  339. static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_psu_items_data[] = {
  340. {
  341. .label = "psu1",
  342. .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
  343. .mask = BIT(0),
  344. .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0],
  345. .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
  346. },
  347. {
  348. .label = "psu2",
  349. .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
  350. .mask = BIT(1),
  351. .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1],
  352. .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
  353. },
  354. };
  355. static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_pwr_items_data[] = {
  356. {
  357. .label = "pwr1",
  358. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  359. .mask = BIT(0),
  360. .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0],
  361. .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
  362. },
  363. {
  364. .label = "pwr2",
  365. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  366. .mask = BIT(1),
  367. .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1],
  368. .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
  369. },
  370. };
  371. static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_fan_items_data[] = {
  372. {
  373. .label = "fan1",
  374. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  375. .mask = BIT(0),
  376. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  377. },
  378. {
  379. .label = "fan2",
  380. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  381. .mask = BIT(1),
  382. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  383. },
  384. {
  385. .label = "fan3",
  386. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  387. .mask = BIT(2),
  388. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  389. },
  390. {
  391. .label = "fan4",
  392. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  393. .mask = BIT(3),
  394. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  395. },
  396. };
  397. static struct mlxreg_core_item mlxplat_mlxcpld_msn274x_items[] = {
  398. {
  399. .data = mlxplat_mlxcpld_msn274x_psu_items_data,
  400. .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
  401. .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
  402. .mask = MLXPLAT_CPLD_PSU_MASK,
  403. .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_psu_items_data),
  404. .inversed = 1,
  405. .health = false,
  406. },
  407. {
  408. .data = mlxplat_mlxcpld_default_ng_pwr_items_data,
  409. .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
  410. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  411. .mask = MLXPLAT_CPLD_PWR_MASK,
  412. .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data),
  413. .inversed = 0,
  414. .health = false,
  415. },
  416. {
  417. .data = mlxplat_mlxcpld_msn274x_fan_items_data,
  418. .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
  419. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  420. .mask = MLXPLAT_CPLD_FAN_MASK,
  421. .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_fan_items_data),
  422. .inversed = 1,
  423. .health = false,
  424. },
  425. };
  426. static
  427. struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn274x_data = {
  428. .items = mlxplat_mlxcpld_msn274x_items,
  429. .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_items),
  430. .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
  431. .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
  432. .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
  433. .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
  434. };
  435. /* Platform hotplug MSN201x system family data */
  436. static struct mlxreg_core_data mlxplat_mlxcpld_msn201x_pwr_items_data[] = {
  437. {
  438. .label = "pwr1",
  439. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  440. .mask = BIT(0),
  441. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  442. },
  443. {
  444. .label = "pwr2",
  445. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  446. .mask = BIT(1),
  447. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  448. },
  449. };
  450. static struct mlxreg_core_item mlxplat_mlxcpld_msn201x_items[] = {
  451. {
  452. .data = mlxplat_mlxcpld_msn201x_pwr_items_data,
  453. .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
  454. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  455. .mask = MLXPLAT_CPLD_PWR_MASK,
  456. .count = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_pwr_items_data),
  457. .inversed = 0,
  458. .health = false,
  459. },
  460. };
  461. static
  462. struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn201x_data = {
  463. .items = mlxplat_mlxcpld_msn21xx_items,
  464. .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_items),
  465. .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
  466. .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
  467. .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
  468. .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
  469. };
  470. /* Platform hotplug next generation system family data */
  471. static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_psu_items_data[] = {
  472. {
  473. .label = "psu1",
  474. .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
  475. .mask = BIT(0),
  476. .hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[0],
  477. .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
  478. },
  479. {
  480. .label = "psu2",
  481. .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
  482. .mask = BIT(1),
  483. .hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[1],
  484. .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
  485. },
  486. };
  487. static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_fan_items_data[] = {
  488. {
  489. .label = "fan1",
  490. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  491. .mask = BIT(0),
  492. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  493. },
  494. {
  495. .label = "fan2",
  496. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  497. .mask = BIT(1),
  498. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  499. },
  500. {
  501. .label = "fan3",
  502. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  503. .mask = BIT(2),
  504. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  505. },
  506. {
  507. .label = "fan4",
  508. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  509. .mask = BIT(3),
  510. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  511. },
  512. {
  513. .label = "fan5",
  514. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  515. .mask = BIT(4),
  516. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  517. },
  518. {
  519. .label = "fan6",
  520. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  521. .mask = BIT(5),
  522. .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
  523. },
  524. };
  525. static struct mlxreg_core_item mlxplat_mlxcpld_default_ng_items[] = {
  526. {
  527. .data = mlxplat_mlxcpld_default_ng_psu_items_data,
  528. .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
  529. .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
  530. .mask = MLXPLAT_CPLD_PSU_MASK,
  531. .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_psu_items_data),
  532. .inversed = 1,
  533. .health = false,
  534. },
  535. {
  536. .data = mlxplat_mlxcpld_default_ng_pwr_items_data,
  537. .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
  538. .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
  539. .mask = MLXPLAT_CPLD_PWR_MASK,
  540. .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data),
  541. .inversed = 0,
  542. .health = false,
  543. },
  544. {
  545. .data = mlxplat_mlxcpld_default_ng_fan_items_data,
  546. .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
  547. .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
  548. .mask = MLXPLAT_CPLD_FAN_NG_MASK,
  549. .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data),
  550. .inversed = 1,
  551. .health = false,
  552. },
  553. };
  554. static
  555. struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_ng_data = {
  556. .items = mlxplat_mlxcpld_default_ng_items,
  557. .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_items),
  558. .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
  559. .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
  560. .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
  561. .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
  562. };
  563. /* Platform led default data */
  564. static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = {
  565. {
  566. .label = "status:green",
  567. .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
  568. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  569. },
  570. {
  571. .label = "status:red",
  572. .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
  573. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
  574. },
  575. {
  576. .label = "psu:green",
  577. .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
  578. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  579. },
  580. {
  581. .label = "psu:red",
  582. .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
  583. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  584. },
  585. {
  586. .label = "fan1:green",
  587. .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
  588. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  589. },
  590. {
  591. .label = "fan1:red",
  592. .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
  593. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  594. },
  595. {
  596. .label = "fan2:green",
  597. .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
  598. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  599. },
  600. {
  601. .label = "fan2:red",
  602. .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
  603. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  604. },
  605. {
  606. .label = "fan3:green",
  607. .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
  608. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  609. },
  610. {
  611. .label = "fan3:red",
  612. .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
  613. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  614. },
  615. {
  616. .label = "fan4:green",
  617. .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
  618. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  619. },
  620. {
  621. .label = "fan4:red",
  622. .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
  623. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  624. },
  625. };
  626. static struct mlxreg_core_platform_data mlxplat_default_led_data = {
  627. .data = mlxplat_mlxcpld_default_led_data,
  628. .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_led_data),
  629. };
  630. /* Platform led MSN21xx system family data */
  631. static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_led_data[] = {
  632. {
  633. .label = "status:green",
  634. .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
  635. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  636. },
  637. {
  638. .label = "status:red",
  639. .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
  640. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
  641. },
  642. {
  643. .label = "fan:green",
  644. .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
  645. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  646. },
  647. {
  648. .label = "fan:red",
  649. .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
  650. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  651. },
  652. {
  653. .label = "psu1:green",
  654. .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
  655. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  656. },
  657. {
  658. .label = "psu1:red",
  659. .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
  660. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  661. },
  662. {
  663. .label = "psu2:green",
  664. .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
  665. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  666. },
  667. {
  668. .label = "psu2:red",
  669. .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
  670. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  671. },
  672. {
  673. .label = "uid:blue",
  674. .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET,
  675. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  676. },
  677. };
  678. static struct mlxreg_core_platform_data mlxplat_msn21xx_led_data = {
  679. .data = mlxplat_mlxcpld_msn21xx_led_data,
  680. .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_led_data),
  681. };
  682. /* Platform led for default data for 200GbE systems */
  683. static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_led_data[] = {
  684. {
  685. .label = "status:green",
  686. .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
  687. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  688. },
  689. {
  690. .label = "status:orange",
  691. .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
  692. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
  693. },
  694. {
  695. .label = "psu:green",
  696. .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
  697. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  698. },
  699. {
  700. .label = "psu:orange",
  701. .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
  702. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  703. },
  704. {
  705. .label = "fan1:green",
  706. .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
  707. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  708. },
  709. {
  710. .label = "fan1:orange",
  711. .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
  712. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  713. },
  714. {
  715. .label = "fan2:green",
  716. .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
  717. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  718. },
  719. {
  720. .label = "fan2:orange",
  721. .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
  722. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  723. },
  724. {
  725. .label = "fan3:green",
  726. .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
  727. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  728. },
  729. {
  730. .label = "fan3:orange",
  731. .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
  732. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  733. },
  734. {
  735. .label = "fan4:green",
  736. .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
  737. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  738. },
  739. {
  740. .label = "fan4:orange",
  741. .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
  742. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  743. },
  744. {
  745. .label = "fan5:green",
  746. .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
  747. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  748. },
  749. {
  750. .label = "fan5:orange",
  751. .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
  752. .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
  753. },
  754. {
  755. .label = "fan6:green",
  756. .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
  757. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  758. },
  759. {
  760. .label = "fan6:orange",
  761. .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
  762. .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
  763. },
  764. };
  765. static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = {
  766. .data = mlxplat_mlxcpld_default_ng_led_data,
  767. .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data),
  768. };
  769. static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
  770. {
  771. switch (reg) {
  772. case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
  773. case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
  774. case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
  775. case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
  776. case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
  777. case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
  778. case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
  779. case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
  780. case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
  781. case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
  782. case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
  783. case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
  784. case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
  785. return true;
  786. }
  787. return false;
  788. }
  789. static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
  790. {
  791. switch (reg) {
  792. case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
  793. case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
  794. case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
  795. case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
  796. case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
  797. case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
  798. case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
  799. case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
  800. case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
  801. case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET:
  802. case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
  803. case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
  804. case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET:
  805. case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
  806. case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
  807. case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
  808. case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
  809. case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
  810. return true;
  811. }
  812. return false;
  813. }
  814. static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
  815. {
  816. switch (reg) {
  817. case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
  818. case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
  819. case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
  820. case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
  821. case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
  822. case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
  823. case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
  824. case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
  825. case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
  826. case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET:
  827. case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
  828. case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
  829. case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET:
  830. case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
  831. case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
  832. case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
  833. case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
  834. case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
  835. return true;
  836. }
  837. return false;
  838. }
  839. struct mlxplat_mlxcpld_regmap_context {
  840. void __iomem *base;
  841. };
  842. static struct mlxplat_mlxcpld_regmap_context mlxplat_mlxcpld_regmap_ctx;
  843. static int
  844. mlxplat_mlxcpld_reg_read(void *context, unsigned int reg, unsigned int *val)
  845. {
  846. struct mlxplat_mlxcpld_regmap_context *ctx = context;
  847. *val = ioread8(ctx->base + reg);
  848. return 0;
  849. }
  850. static int
  851. mlxplat_mlxcpld_reg_write(void *context, unsigned int reg, unsigned int val)
  852. {
  853. struct mlxplat_mlxcpld_regmap_context *ctx = context;
  854. iowrite8(val, ctx->base + reg);
  855. return 0;
  856. }
  857. static const struct regmap_config mlxplat_mlxcpld_regmap_config = {
  858. .reg_bits = 8,
  859. .val_bits = 8,
  860. .max_register = 255,
  861. .cache_type = REGCACHE_FLAT,
  862. .writeable_reg = mlxplat_mlxcpld_writeable_reg,
  863. .readable_reg = mlxplat_mlxcpld_readable_reg,
  864. .volatile_reg = mlxplat_mlxcpld_volatile_reg,
  865. .reg_read = mlxplat_mlxcpld_reg_read,
  866. .reg_write = mlxplat_mlxcpld_reg_write,
  867. };
  868. static struct resource mlxplat_mlxcpld_resources[] = {
  869. [0] = DEFINE_RES_IRQ_NAMED(17, "mlxreg-hotplug"),
  870. };
  871. static struct platform_device *mlxplat_dev;
  872. static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
  873. static struct mlxreg_core_platform_data *mlxplat_led;
  874. static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
  875. {
  876. int i;
  877. for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
  878. mlxplat_mux_data[i].values = mlxplat_default_channels[i];
  879. mlxplat_mux_data[i].n_values =
  880. ARRAY_SIZE(mlxplat_default_channels[i]);
  881. }
  882. mlxplat_hotplug = &mlxplat_mlxcpld_default_data;
  883. mlxplat_hotplug->deferred_nr =
  884. mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
  885. mlxplat_led = &mlxplat_default_led_data;
  886. return 1;
  887. };
  888. static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
  889. {
  890. int i;
  891. for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
  892. mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
  893. mlxplat_mux_data[i].n_values =
  894. ARRAY_SIZE(mlxplat_msn21xx_channels);
  895. }
  896. mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data;
  897. mlxplat_hotplug->deferred_nr =
  898. mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
  899. mlxplat_led = &mlxplat_msn21xx_led_data;
  900. return 1;
  901. };
  902. static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
  903. {
  904. int i;
  905. for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
  906. mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
  907. mlxplat_mux_data[i].n_values =
  908. ARRAY_SIZE(mlxplat_msn21xx_channels);
  909. }
  910. mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data;
  911. mlxplat_hotplug->deferred_nr =
  912. mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
  913. mlxplat_led = &mlxplat_default_led_data;
  914. return 1;
  915. };
  916. static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
  917. {
  918. int i;
  919. for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
  920. mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
  921. mlxplat_mux_data[i].n_values =
  922. ARRAY_SIZE(mlxplat_msn21xx_channels);
  923. }
  924. mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data;
  925. mlxplat_hotplug->deferred_nr =
  926. mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
  927. mlxplat_led = &mlxplat_default_ng_led_data;
  928. return 1;
  929. };
  930. static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
  931. {
  932. int i;
  933. for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
  934. mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
  935. mlxplat_mux_data[i].n_values =
  936. ARRAY_SIZE(mlxplat_msn21xx_channels);
  937. }
  938. mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data;
  939. mlxplat_hotplug->deferred_nr =
  940. mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
  941. mlxplat_led = &mlxplat_msn21xx_led_data;
  942. return 1;
  943. };
  944. static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
  945. {
  946. .callback = mlxplat_dmi_msn274x_matched,
  947. .matches = {
  948. DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
  949. DMI_MATCH(DMI_PRODUCT_NAME, "MSN274"),
  950. },
  951. },
  952. {
  953. .callback = mlxplat_dmi_default_matched,
  954. .matches = {
  955. DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
  956. DMI_MATCH(DMI_PRODUCT_NAME, "MSN24"),
  957. },
  958. },
  959. {
  960. .callback = mlxplat_dmi_default_matched,
  961. .matches = {
  962. DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
  963. DMI_MATCH(DMI_PRODUCT_NAME, "MSN27"),
  964. },
  965. },
  966. {
  967. .callback = mlxplat_dmi_default_matched,
  968. .matches = {
  969. DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
  970. DMI_MATCH(DMI_PRODUCT_NAME, "MSB"),
  971. },
  972. },
  973. {
  974. .callback = mlxplat_dmi_default_matched,
  975. .matches = {
  976. DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
  977. DMI_MATCH(DMI_PRODUCT_NAME, "MSX"),
  978. },
  979. },
  980. {
  981. .callback = mlxplat_dmi_msn21xx_matched,
  982. .matches = {
  983. DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
  984. DMI_MATCH(DMI_PRODUCT_NAME, "MSN21"),
  985. },
  986. },
  987. {
  988. .callback = mlxplat_dmi_msn201x_matched,
  989. .matches = {
  990. DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
  991. DMI_MATCH(DMI_PRODUCT_NAME, "MSN201"),
  992. },
  993. },
  994. {
  995. .callback = mlxplat_dmi_qmb7xx_matched,
  996. .matches = {
  997. DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
  998. DMI_MATCH(DMI_PRODUCT_NAME, "QMB7"),
  999. },
  1000. },
  1001. {
  1002. .callback = mlxplat_dmi_qmb7xx_matched,
  1003. .matches = {
  1004. DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
  1005. DMI_MATCH(DMI_PRODUCT_NAME, "SN37"),
  1006. },
  1007. },
  1008. {
  1009. .callback = mlxplat_dmi_qmb7xx_matched,
  1010. .matches = {
  1011. DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
  1012. DMI_MATCH(DMI_PRODUCT_NAME, "SN34"),
  1013. },
  1014. },
  1015. {
  1016. .callback = mlxplat_dmi_default_matched,
  1017. .matches = {
  1018. DMI_MATCH(DMI_BOARD_NAME, "VMOD0001"),
  1019. },
  1020. },
  1021. {
  1022. .callback = mlxplat_dmi_msn21xx_matched,
  1023. .matches = {
  1024. DMI_MATCH(DMI_BOARD_NAME, "VMOD0002"),
  1025. },
  1026. },
  1027. {
  1028. .callback = mlxplat_dmi_msn274x_matched,
  1029. .matches = {
  1030. DMI_MATCH(DMI_BOARD_NAME, "VMOD0003"),
  1031. },
  1032. },
  1033. {
  1034. .callback = mlxplat_dmi_msn201x_matched,
  1035. .matches = {
  1036. DMI_MATCH(DMI_BOARD_NAME, "VMOD0004"),
  1037. },
  1038. },
  1039. {
  1040. .callback = mlxplat_dmi_qmb7xx_matched,
  1041. .matches = {
  1042. DMI_MATCH(DMI_BOARD_NAME, "VMOD0005"),
  1043. },
  1044. },
  1045. { }
  1046. };
  1047. MODULE_DEVICE_TABLE(dmi, mlxplat_dmi_table);
  1048. static int mlxplat_mlxcpld_verify_bus_topology(int *nr)
  1049. {
  1050. struct i2c_adapter *search_adap;
  1051. int shift, i;
  1052. /* Scan adapters from expected id to verify it is free. */
  1053. *nr = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR;
  1054. for (i = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; i <
  1055. MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; i++) {
  1056. search_adap = i2c_get_adapter(i);
  1057. if (search_adap) {
  1058. i2c_put_adapter(search_adap);
  1059. continue;
  1060. }
  1061. /* Return if expected parent adapter is free. */
  1062. if (i == MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR)
  1063. return 0;
  1064. break;
  1065. }
  1066. /* Return with error if free id for adapter is not found. */
  1067. if (i == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM)
  1068. return -ENODEV;
  1069. /* Shift adapter ids, since expected parent adapter is not free. */
  1070. *nr = i;
  1071. for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
  1072. shift = *nr - mlxplat_mux_data[i].parent;
  1073. mlxplat_mux_data[i].parent = *nr;
  1074. mlxplat_mux_data[i].base_nr += shift;
  1075. if (shift > 0)
  1076. mlxplat_hotplug->shift_nr = shift;
  1077. }
  1078. return 0;
  1079. }
  1080. static int __init mlxplat_init(void)
  1081. {
  1082. struct mlxplat_priv *priv;
  1083. int i, nr, err;
  1084. if (!dmi_check_system(mlxplat_dmi_table))
  1085. return -ENODEV;
  1086. mlxplat_dev = platform_device_register_simple(MLX_PLAT_DEVICE_NAME, -1,
  1087. mlxplat_lpc_resources,
  1088. ARRAY_SIZE(mlxplat_lpc_resources));
  1089. if (IS_ERR(mlxplat_dev))
  1090. return PTR_ERR(mlxplat_dev);
  1091. priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv),
  1092. GFP_KERNEL);
  1093. if (!priv) {
  1094. err = -ENOMEM;
  1095. goto fail_alloc;
  1096. }
  1097. platform_set_drvdata(mlxplat_dev, priv);
  1098. err = mlxplat_mlxcpld_verify_bus_topology(&nr);
  1099. if (nr < 0)
  1100. goto fail_alloc;
  1101. nr = (nr == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM) ? -1 : nr;
  1102. priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", nr,
  1103. NULL, 0);
  1104. if (IS_ERR(priv->pdev_i2c)) {
  1105. err = PTR_ERR(priv->pdev_i2c);
  1106. goto fail_alloc;
  1107. }
  1108. for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
  1109. priv->pdev_mux[i] = platform_device_register_resndata(
  1110. &mlxplat_dev->dev,
  1111. "i2c-mux-reg", i, NULL,
  1112. 0, &mlxplat_mux_data[i],
  1113. sizeof(mlxplat_mux_data[i]));
  1114. if (IS_ERR(priv->pdev_mux[i])) {
  1115. err = PTR_ERR(priv->pdev_mux[i]);
  1116. goto fail_platform_mux_register;
  1117. }
  1118. }
  1119. mlxplat_mlxcpld_regmap_ctx.base = devm_ioport_map(&mlxplat_dev->dev,
  1120. mlxplat_lpc_resources[1].start, 1);
  1121. if (!mlxplat_mlxcpld_regmap_ctx.base) {
  1122. err = -ENOMEM;
  1123. goto fail_platform_mux_register;
  1124. }
  1125. mlxplat_hotplug->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL,
  1126. &mlxplat_mlxcpld_regmap_ctx,
  1127. &mlxplat_mlxcpld_regmap_config);
  1128. if (IS_ERR(mlxplat_hotplug->regmap)) {
  1129. err = PTR_ERR(mlxplat_hotplug->regmap);
  1130. goto fail_platform_mux_register;
  1131. }
  1132. priv->pdev_hotplug = platform_device_register_resndata(
  1133. &mlxplat_dev->dev, "mlxreg-hotplug",
  1134. PLATFORM_DEVID_NONE,
  1135. mlxplat_mlxcpld_resources,
  1136. ARRAY_SIZE(mlxplat_mlxcpld_resources),
  1137. mlxplat_hotplug, sizeof(*mlxplat_hotplug));
  1138. if (IS_ERR(priv->pdev_hotplug)) {
  1139. err = PTR_ERR(priv->pdev_hotplug);
  1140. goto fail_platform_mux_register;
  1141. }
  1142. /* Add LED driver. */
  1143. mlxplat_led->regmap = mlxplat_hotplug->regmap;
  1144. priv->pdev_led = platform_device_register_resndata(
  1145. &mlxplat_dev->dev, "leds-mlxreg",
  1146. PLATFORM_DEVID_NONE, NULL, 0,
  1147. mlxplat_led, sizeof(*mlxplat_led));
  1148. if (IS_ERR(priv->pdev_led)) {
  1149. err = PTR_ERR(priv->pdev_led);
  1150. goto fail_platform_hotplug_register;
  1151. }
  1152. /* Sync registers with hardware. */
  1153. regcache_mark_dirty(mlxplat_hotplug->regmap);
  1154. err = regcache_sync(mlxplat_hotplug->regmap);
  1155. if (err)
  1156. goto fail_platform_led_register;
  1157. return 0;
  1158. fail_platform_led_register:
  1159. platform_device_unregister(priv->pdev_led);
  1160. fail_platform_hotplug_register:
  1161. platform_device_unregister(priv->pdev_hotplug);
  1162. fail_platform_mux_register:
  1163. while (--i >= 0)
  1164. platform_device_unregister(priv->pdev_mux[i]);
  1165. platform_device_unregister(priv->pdev_i2c);
  1166. fail_alloc:
  1167. platform_device_unregister(mlxplat_dev);
  1168. return err;
  1169. }
  1170. module_init(mlxplat_init);
  1171. static void __exit mlxplat_exit(void)
  1172. {
  1173. struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
  1174. int i;
  1175. platform_device_unregister(priv->pdev_led);
  1176. platform_device_unregister(priv->pdev_hotplug);
  1177. for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--)
  1178. platform_device_unregister(priv->pdev_mux[i]);
  1179. platform_device_unregister(priv->pdev_i2c);
  1180. platform_device_unregister(mlxplat_dev);
  1181. }
  1182. module_exit(mlxplat_exit);
  1183. MODULE_AUTHOR("Vadim Pasternak (vadimp@mellanox.com)");
  1184. MODULE_DESCRIPTION("Mellanox platform driver");
  1185. MODULE_LICENSE("Dual BSD/GPL");