global2_scratch.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Marvell 88E6xxx Switch Global 2 Scratch & Misc Registers support
  4. *
  5. * Copyright (c) 2008 Marvell Semiconductor
  6. *
  7. * Copyright (c) 2017 National Instruments
  8. * Brandon Streiff <[email protected]>
  9. */
  10. #include "chip.h"
  11. #include "global2.h"
  12. /* Offset 0x1A: Scratch and Misc. Register */
  13. static int mv88e6xxx_g2_scratch_read(struct mv88e6xxx_chip *chip, int reg,
  14. u8 *data)
  15. {
  16. u16 value;
  17. int err;
  18. err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC,
  19. reg << 8);
  20. if (err)
  21. return err;
  22. err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC, &value);
  23. if (err)
  24. return err;
  25. *data = (value & MV88E6XXX_G2_SCRATCH_MISC_DATA_MASK);
  26. return 0;
  27. }
  28. static int mv88e6xxx_g2_scratch_write(struct mv88e6xxx_chip *chip, int reg,
  29. u8 data)
  30. {
  31. u16 value = (reg << 8) | data;
  32. return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC,
  33. MV88E6XXX_G2_SCRATCH_MISC_UPDATE | value);
  34. }
  35. /**
  36. * mv88e6xxx_g2_scratch_get_bit - get a bit
  37. * @chip: chip private data
  38. * @base_reg: base of scratch bits
  39. * @offset: index of bit within the register
  40. * @set: is bit set?
  41. */
  42. static int mv88e6xxx_g2_scratch_get_bit(struct mv88e6xxx_chip *chip,
  43. int base_reg, unsigned int offset,
  44. int *set)
  45. {
  46. int reg = base_reg + (offset / 8);
  47. u8 mask = (1 << (offset & 0x7));
  48. u8 val;
  49. int err;
  50. err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
  51. if (err)
  52. return err;
  53. *set = !!(mask & val);
  54. return 0;
  55. }
  56. /**
  57. * mv88e6xxx_g2_scratch_set_bit - set (or clear) a bit
  58. * @chip: chip private data
  59. * @base_reg: base of scratch bits
  60. * @offset: index of bit within the register
  61. * @set: should this bit be set?
  62. *
  63. * Helper function for dealing with the direction and data registers.
  64. */
  65. static int mv88e6xxx_g2_scratch_set_bit(struct mv88e6xxx_chip *chip,
  66. int base_reg, unsigned int offset,
  67. int set)
  68. {
  69. int reg = base_reg + (offset / 8);
  70. u8 mask = (1 << (offset & 0x7));
  71. u8 val;
  72. int err;
  73. err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
  74. if (err)
  75. return err;
  76. if (set)
  77. val |= mask;
  78. else
  79. val &= ~mask;
  80. return mv88e6xxx_g2_scratch_write(chip, reg, val);
  81. }
  82. /**
  83. * mv88e6352_g2_scratch_gpio_get_data - get data on gpio pin
  84. * @chip: chip private data
  85. * @pin: gpio index
  86. *
  87. * Return: 0 for low, 1 for high, negative error
  88. */
  89. static int mv88e6352_g2_scratch_gpio_get_data(struct mv88e6xxx_chip *chip,
  90. unsigned int pin)
  91. {
  92. int val = 0;
  93. int err;
  94. err = mv88e6xxx_g2_scratch_get_bit(chip,
  95. MV88E6352_G2_SCRATCH_GPIO_DATA0,
  96. pin, &val);
  97. if (err)
  98. return err;
  99. return val;
  100. }
  101. /**
  102. * mv88e6352_g2_scratch_gpio_set_data - set data on gpio pin
  103. * @chip: chip private data
  104. * @pin: gpio index
  105. * @value: value to set
  106. */
  107. static int mv88e6352_g2_scratch_gpio_set_data(struct mv88e6xxx_chip *chip,
  108. unsigned int pin, int value)
  109. {
  110. u8 mask = (1 << (pin & 0x7));
  111. int offset = (pin / 8);
  112. int reg;
  113. reg = MV88E6352_G2_SCRATCH_GPIO_DATA0 + offset;
  114. if (value)
  115. chip->gpio_data[offset] |= mask;
  116. else
  117. chip->gpio_data[offset] &= ~mask;
  118. return mv88e6xxx_g2_scratch_write(chip, reg, chip->gpio_data[offset]);
  119. }
  120. /**
  121. * mv88e6352_g2_scratch_gpio_get_dir - get direction of gpio pin
  122. * @chip: chip private data
  123. * @pin: gpio index
  124. *
  125. * Return: 0 for output, 1 for input (same as GPIOF_DIR_XXX).
  126. */
  127. static int mv88e6352_g2_scratch_gpio_get_dir(struct mv88e6xxx_chip *chip,
  128. unsigned int pin)
  129. {
  130. int val = 0;
  131. int err;
  132. err = mv88e6xxx_g2_scratch_get_bit(chip,
  133. MV88E6352_G2_SCRATCH_GPIO_DIR0,
  134. pin, &val);
  135. if (err)
  136. return err;
  137. return val;
  138. }
  139. /**
  140. * mv88e6352_g2_scratch_gpio_set_dir - set direction of gpio pin
  141. * @chip: chip private data
  142. * @pin: gpio index
  143. * @input: should the gpio be an input, or an output?
  144. */
  145. static int mv88e6352_g2_scratch_gpio_set_dir(struct mv88e6xxx_chip *chip,
  146. unsigned int pin, bool input)
  147. {
  148. int value = (input ? MV88E6352_G2_SCRATCH_GPIO_DIR_IN :
  149. MV88E6352_G2_SCRATCH_GPIO_DIR_OUT);
  150. return mv88e6xxx_g2_scratch_set_bit(chip,
  151. MV88E6352_G2_SCRATCH_GPIO_DIR0,
  152. pin, value);
  153. }
  154. /**
  155. * mv88e6352_g2_scratch_gpio_get_pctl - get pin control setting
  156. * @chip: chip private data
  157. * @pin: gpio index
  158. * @func: function number
  159. *
  160. * Note that the function numbers themselves may vary by chipset.
  161. */
  162. static int mv88e6352_g2_scratch_gpio_get_pctl(struct mv88e6xxx_chip *chip,
  163. unsigned int pin, int *func)
  164. {
  165. int reg = MV88E6352_G2_SCRATCH_GPIO_PCTL0 + (pin / 2);
  166. int offset = (pin & 0x1) ? 4 : 0;
  167. u8 mask = (0x7 << offset);
  168. int err;
  169. u8 val;
  170. err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
  171. if (err)
  172. return err;
  173. *func = (val & mask) >> offset;
  174. return 0;
  175. }
  176. /**
  177. * mv88e6352_g2_scratch_gpio_set_pctl - set pin control setting
  178. * @chip: chip private data
  179. * @pin: gpio index
  180. * @func: function number
  181. */
  182. static int mv88e6352_g2_scratch_gpio_set_pctl(struct mv88e6xxx_chip *chip,
  183. unsigned int pin, int func)
  184. {
  185. int reg = MV88E6352_G2_SCRATCH_GPIO_PCTL0 + (pin / 2);
  186. int offset = (pin & 0x1) ? 4 : 0;
  187. u8 mask = (0x7 << offset);
  188. int err;
  189. u8 val;
  190. err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
  191. if (err)
  192. return err;
  193. val = (val & ~mask) | ((func & mask) << offset);
  194. return mv88e6xxx_g2_scratch_write(chip, reg, val);
  195. }
  196. const struct mv88e6xxx_gpio_ops mv88e6352_gpio_ops = {
  197. .get_data = mv88e6352_g2_scratch_gpio_get_data,
  198. .set_data = mv88e6352_g2_scratch_gpio_set_data,
  199. .get_dir = mv88e6352_g2_scratch_gpio_get_dir,
  200. .set_dir = mv88e6352_g2_scratch_gpio_set_dir,
  201. .get_pctl = mv88e6352_g2_scratch_gpio_get_pctl,
  202. .set_pctl = mv88e6352_g2_scratch_gpio_set_pctl,
  203. };
  204. /**
  205. * mv88e6xxx_g2_scratch_gpio_set_smi - set gpio muxing for external smi
  206. * @chip: chip private data
  207. * @external: set mux for external smi, or free for gpio usage
  208. *
  209. * Some mv88e6xxx models have GPIO pins that may be configured as
  210. * an external SMI interface, or they may be made free for other
  211. * GPIO uses.
  212. */
  213. int mv88e6xxx_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip *chip,
  214. bool external)
  215. {
  216. int misc_cfg = MV88E6352_G2_SCRATCH_MISC_CFG;
  217. int config_data1 = MV88E6352_G2_SCRATCH_CONFIG_DATA1;
  218. int config_data2 = MV88E6352_G2_SCRATCH_CONFIG_DATA2;
  219. bool no_cpu;
  220. u8 p0_mode;
  221. int err;
  222. u8 val;
  223. err = mv88e6xxx_g2_scratch_read(chip, config_data2, &val);
  224. if (err)
  225. return err;
  226. p0_mode = val & MV88E6352_G2_SCRATCH_CONFIG_DATA2_P0_MODE_MASK;
  227. if (p0_mode == 0x01 || p0_mode == 0x02)
  228. return -EBUSY;
  229. err = mv88e6xxx_g2_scratch_read(chip, config_data1, &val);
  230. if (err)
  231. return err;
  232. no_cpu = !!(val & MV88E6352_G2_SCRATCH_CONFIG_DATA1_NO_CPU);
  233. err = mv88e6xxx_g2_scratch_read(chip, misc_cfg, &val);
  234. if (err)
  235. return err;
  236. /* NO_CPU being 0 inverts the meaning of the bit */
  237. if (!no_cpu)
  238. external = !external;
  239. if (external)
  240. val |= MV88E6352_G2_SCRATCH_MISC_CFG_NORMALSMI;
  241. else
  242. val &= ~MV88E6352_G2_SCRATCH_MISC_CFG_NORMALSMI;
  243. return mv88e6xxx_g2_scratch_write(chip, misc_cfg, val);
  244. }
  245. /**
  246. * mv88e6352_g2_scratch_port_has_serdes - indicate if a port can have a serdes
  247. * @chip: chip private data
  248. * @port: port number to check for serdes
  249. *
  250. * Indicates whether the port may have a serdes attached according to the
  251. * pin strapping. Returns negative error number, 0 if the port is not
  252. * configured to have a serdes, and 1 if the port is configured to have a
  253. * serdes attached.
  254. */
  255. int mv88e6352_g2_scratch_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
  256. {
  257. u8 config3, p;
  258. int err;
  259. err = mv88e6xxx_g2_scratch_read(chip, MV88E6352_G2_SCRATCH_CONFIG_DATA3,
  260. &config3);
  261. if (err)
  262. return err;
  263. if (config3 & MV88E6352_G2_SCRATCH_CONFIG_DATA3_S_SEL)
  264. p = 5;
  265. else
  266. p = 4;
  267. return port == p;
  268. }