cvmx-helper-fdt.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Copyright (C) 2020 Marvell International Ltd.
  4. *
  5. * FDT Helper functions similar to those provided to U-Boot.
  6. * If compiled for U-Boot, just provide wrappers to the equivalent U-Boot
  7. * functions.
  8. */
  9. #ifndef __CVMX_HELPER_FDT_H__
  10. #define __CVMX_HELPER_FDT_H__
  11. #include <fdt_support.h>
  12. #include <fdtdec.h>
  13. #include <time.h>
  14. #include <asm/global_data.h>
  15. #include <linux/libfdt.h>
  16. #include <mach/cvmx-helper-sfp.h>
  17. enum cvmx_i2c_bus_type {
  18. CVMX_I2C_BUS_OCTEON,
  19. CVMX_I2C_MUX_PCA9540,
  20. CVMX_I2C_MUX_PCA9542,
  21. CVMX_I2C_MUX_PCA9543,
  22. CVMX_I2C_MUX_PCA9544,
  23. CVMX_I2C_MUX_PCA9545,
  24. CVMX_I2C_MUX_PCA9546,
  25. CVMX_I2C_MUX_PCA9547,
  26. CVMX_I2C_MUX_PCA9548,
  27. CVMX_I2C_MUX_OTHER
  28. };
  29. struct cvmx_sfp_mod_info; /** Defined in cvmx-helper-sfp.h */
  30. struct cvmx_phy_info; /** Defined in cvmx-helper-board.h */
  31. /**
  32. * This data structure holds information about various I2C muxes and switches
  33. * that may be between a device and the Octeon chip.
  34. */
  35. struct cvmx_fdt_i2c_bus_info {
  36. /** Parent I2C bus, NULL if root */
  37. struct cvmx_fdt_i2c_bus_info *parent;
  38. /** Child I2C bus or NULL if last entry in the chain */
  39. struct cvmx_fdt_i2c_bus_info *child;
  40. /** Offset in device tree */
  41. int of_offset;
  42. /** Type of i2c bus or mux */
  43. enum cvmx_i2c_bus_type type;
  44. /** I2C address of mux */
  45. u8 i2c_addr;
  46. /** Mux channel number */
  47. u8 channel;
  48. /** For muxes, the bit(s) to set to enable them */
  49. u8 enable_bit;
  50. /** True if mux, false if switch */
  51. bool is_mux;
  52. };
  53. /**
  54. * Data structure containing information about SFP/QSFP slots
  55. */
  56. struct cvmx_fdt_sfp_info {
  57. /** Used for a linked list of slots */
  58. struct cvmx_fdt_sfp_info *next, *prev;
  59. /** Used when multiple SFP ports share the same IPD port */
  60. struct cvmx_fdt_sfp_info *next_iface_sfp;
  61. /** Name from device tree of slot */
  62. const char *name;
  63. /** I2C bus for slot EEPROM */
  64. struct cvmx_fdt_i2c_bus_info *i2c_bus;
  65. /** Data from SFP or QSFP EEPROM */
  66. struct cvmx_sfp_mod_info sfp_info;
  67. /** Data structure with PHY information */
  68. struct cvmx_phy_info *phy_info;
  69. /** IPD port(s) slot is connected to */
  70. int ipd_port[4];
  71. /** Offset in device tree of slot */
  72. int of_offset;
  73. /** EEPROM address of SFP module (usually 0x50) */
  74. u8 i2c_eeprom_addr;
  75. /** Diagnostic address of SFP module (usually 0x51) */
  76. u8 i2c_diag_addr;
  77. /** True if QSFP module */
  78. bool is_qsfp;
  79. /** True if EEPROM data is valid */
  80. bool valid;
  81. /** SFP tx_disable GPIO descriptor */
  82. struct cvmx_fdt_gpio_info *tx_disable;
  83. /** SFP mod_abs/QSFP mod_prs GPIO descriptor */
  84. struct cvmx_fdt_gpio_info *mod_abs;
  85. /** SFP tx_error GPIO descriptor */
  86. struct cvmx_fdt_gpio_info *tx_error;
  87. /** SFP rx_los GPIO discriptor */
  88. struct cvmx_fdt_gpio_info *rx_los;
  89. /** QSFP select GPIO descriptor */
  90. struct cvmx_fdt_gpio_info *select;
  91. /** QSFP reset GPIO descriptor */
  92. struct cvmx_fdt_gpio_info *reset;
  93. /** QSFP interrupt GPIO descriptor */
  94. struct cvmx_fdt_gpio_info *interrupt;
  95. /** QSFP lp_mode GPIO descriptor */
  96. struct cvmx_fdt_gpio_info *lp_mode;
  97. /** Last mod_abs value */
  98. int last_mod_abs;
  99. /** Last rx_los value */
  100. int last_rx_los;
  101. /** Function to call to check mod_abs */
  102. int (*check_mod_abs)(struct cvmx_fdt_sfp_info *sfp_info, void *data);
  103. /** User-defined data to pass to check_mod_abs */
  104. void *mod_abs_data;
  105. /** Function to call when mod_abs changes */
  106. int (*mod_abs_changed)(struct cvmx_fdt_sfp_info *sfp_info, int val, void *data);
  107. /** User-defined data to pass to mod_abs_changed */
  108. void *mod_abs_changed_data;
  109. /** Function to call when rx_los changes */
  110. int (*rx_los_changed)(struct cvmx_fdt_sfp_info *sfp_info, int val, void *data);
  111. /** User-defined data to pass to rx_los_changed */
  112. void *rx_los_changed_data;
  113. /** True if we're connected to a Microsemi VSC7224 reclocking chip */
  114. bool is_vsc7224;
  115. /** Data structure for first vsc7224 channel we're attached to */
  116. struct cvmx_vsc7224_chan *vsc7224_chan;
  117. /** True if we're connected to a Avago AVSP5410 phy */
  118. bool is_avsp5410;
  119. /** Data structure for avsp5410 phy we're attached to */
  120. struct cvmx_avsp5410 *avsp5410;
  121. /** xinterface we're on */
  122. int xiface;
  123. /** port index */
  124. int index;
  125. };
  126. /**
  127. * Look up a phandle and follow it to its node then return the offset of that
  128. * node.
  129. *
  130. * @param[in] fdt_addr pointer to FDT blob
  131. * @param node node to read phandle from
  132. * @param[in] prop_name name of property to find
  133. * @param[in,out] lenp Number of phandles, input max number
  134. * @param[out] nodes Array of phandle nodes
  135. *
  136. * Return: -ve error code on error or 0 for success
  137. */
  138. int cvmx_fdt_lookup_phandles(const void *fdt_addr, int node, const char *prop_name, int *lenp,
  139. int *nodes);
  140. /**
  141. * Helper to return the address property
  142. *
  143. * @param[in] fdt_addr pointer to FDT blob
  144. * @param node node to read address from
  145. * @param prop_name property name to read
  146. *
  147. * Return: address of property or FDT_ADDR_T_NONE if not found
  148. */
  149. static inline fdt_addr_t cvmx_fdt_get_addr(const void *fdt_addr, int node, const char *prop_name)
  150. {
  151. return fdtdec_get_addr(fdt_addr, node, prop_name);
  152. }
  153. /**
  154. * Helper function to return an integer property
  155. *
  156. * @param[in] fdt_addr pointer to FDT blob
  157. * @param node node to read integer from
  158. * @param[in] prop_name property name to read
  159. * @param default_val default value to return if property doesn't exist
  160. *
  161. * Return: integer value of property or default_val if it doesn't exist.
  162. */
  163. static inline int cvmx_fdt_get_int(const void *fdt_addr, int node, const char *prop_name,
  164. int default_val)
  165. {
  166. return fdtdec_get_int(fdt_addr, node, prop_name, default_val);
  167. }
  168. static inline bool cvmx_fdt_get_bool(const void *fdt_addr, int node, const char *prop_name)
  169. {
  170. return fdtdec_get_bool(fdt_addr, node, prop_name);
  171. }
  172. static inline u64 cvmx_fdt_get_uint64(const void *fdt_addr, int node, const char *prop_name,
  173. u64 default_val)
  174. {
  175. return fdtdec_get_uint64(fdt_addr, node, prop_name, default_val);
  176. }
  177. /**
  178. * Look up a phandle and follow it to its node then return the offset of that
  179. * node.
  180. *
  181. * @param[in] fdt_addr pointer to FDT blob
  182. * @param node node to read phandle from
  183. * @param[in] prop_name name of property to find
  184. *
  185. * Return: node offset if found, -ve error code on error
  186. */
  187. static inline int cvmx_fdt_lookup_phandle(const void *fdt_addr, int node, const char *prop_name)
  188. {
  189. return fdtdec_lookup_phandle(fdt_addr, node, prop_name);
  190. }
  191. /**
  192. * Translate an address from the device tree into a CPU physical address by
  193. * walking up the device tree and applying bus mappings along the way.
  194. *
  195. * This uses #size-cells and #address-cells.
  196. *
  197. * @param[in] fdt_addr Address of flat device tree
  198. * @param node node to start translating from
  199. * @param[in] in_addr Address to translate
  200. * NOTE: in_addr must be in the native ENDIAN
  201. * format.
  202. *
  203. * Return: Translated address or FDT_ADDR_T_NONE if address cannot be
  204. * translated.
  205. */
  206. static inline u64 cvmx_fdt_translate_address(const void *fdt_addr, int node, const u32 *in_addr)
  207. {
  208. return fdt_translate_address((void *)fdt_addr, node, in_addr);
  209. }
  210. /**
  211. * Compare compatibile strings in the flat device tree.
  212. *
  213. * @param[in] s1 First string to compare
  214. * @param[in] sw Second string to compare
  215. *
  216. * Return: 0 if no match
  217. * 1 if only the part number matches and not the manufacturer
  218. * 2 if both the part number and manufacturer match
  219. */
  220. int cvmx_fdt_compat_match(const char *s1, const char *s2);
  221. /**
  222. * Returns whether a list of strings contains the specified string
  223. *
  224. * @param[in] slist String list
  225. * @param llen string list total length
  226. * @param[in] str string to search for
  227. *
  228. * Return: 1 if string list contains string, 0 if it does not.
  229. */
  230. int cvmx_fdt_compat_list_contains(const char *slist, int llen, const char *str);
  231. /**
  232. * Check if a node is compatible with the specified compat string
  233. *
  234. * @param[in] fdt_addr FDT address
  235. * @param node node offset to check
  236. * @param[in] compat compatible string to check
  237. *
  238. * Return: 0 if compatible, 1 if not compatible, error if negative
  239. */
  240. int cvmx_fdt_node_check_compatible(const void *fdt_addr, int node, const char *compat);
  241. /**
  242. * @INTERNAL
  243. * Compares a string to a compatible field.
  244. *
  245. * @param[in] compat compatible string
  246. * @param[in] str string to check
  247. *
  248. * Return: 0 if not compatible, 1 if manufacturer compatible, 2 if
  249. * part is compatible, 3 if both part and manufacturer are
  250. * compatible.
  251. */
  252. int __cvmx_fdt_compat_match(const char *compat, const char *str);
  253. /**
  254. * Given a phandle to a GPIO device return the type of GPIO device it is.
  255. *
  256. * @param[in] fdt_addr Address of flat device tree
  257. * @param phandle phandle to GPIO
  258. * @param[out] size Number of pins (optional, may be NULL)
  259. *
  260. * Return: Type of GPIO device or PIN_ERROR if error
  261. */
  262. enum cvmx_gpio_type cvmx_fdt_get_gpio_type(const void *fdt_addr, int phandle, int *size);
  263. /**
  264. * Given a phandle to a GPIO node output the i2c bus and address
  265. *
  266. * @param[in] fdt_addr Address of FDT
  267. * @param phandle phandle of GPIO device
  268. * @param[out] bus TWSI bus number with node in bits 1-3, can be
  269. * NULL for none.
  270. * @param[out] addr TWSI address number, can be NULL for none
  271. *
  272. * Return: 0 for success, error otherwise
  273. */
  274. int cvmx_fdt_get_twsi_gpio_bus_addr(const void *fdt_addr, int phandle, int *bus, int *addr);
  275. /**
  276. * Given a FDT node return the CPU node number
  277. *
  278. * @param[in] fdt_addr Address of FDT
  279. * @param node FDT node number
  280. *
  281. * Return: CPU node number or error if negative
  282. */
  283. int cvmx_fdt_get_cpu_node(const void *fdt_addr, int node);
  284. /**
  285. * Get the total size of the flat device tree
  286. *
  287. * @param[in] fdt_addr Address of FDT
  288. *
  289. * Return: Size of flat device tree in bytes or -1 if error.
  290. */
  291. int cvmx_fdt_get_fdt_size(const void *fdt_addr);
  292. /**
  293. * Returns if a node is compatible with one of the items in the string list
  294. *
  295. * @param[in] fdt_addr Pointer to flat device tree
  296. * @param node Node offset to check
  297. * @param[in] strlist Array of FDT device compatibility strings,
  298. * must end with NULL or empty string.
  299. *
  300. * Return: 0 if at least one item matches, 1 if no matches
  301. */
  302. int cvmx_fdt_node_check_compatible_list(const void *fdt_addr, int node, const char *const *strlist);
  303. /**
  304. * Given a FDT node, return the next compatible node.
  305. *
  306. * @param[in] fdt_addr Pointer to flat device tree
  307. * @param start_offset Starting node offset or -1 to find the first
  308. * @param strlist Array of FDT device compatibility strings, must
  309. * end with NULL or empty string.
  310. *
  311. * Return: next matching node or -1 if no more matches.
  312. */
  313. int cvmx_fdt_node_offset_by_compatible_list(const void *fdt_addr, int startoffset,
  314. const char *const *strlist);
  315. /**
  316. * Given the parent offset of an i2c device build up a list describing the bus
  317. * which can contain i2c muxes and switches.
  318. *
  319. * @param[in] fdt_addr address of device tree
  320. * @param of_offset Offset of the parent node of a GPIO device in
  321. * the device tree.
  322. *
  323. * Return: pointer to list of i2c devices starting from the root which
  324. * can include i2c muxes and switches or NULL if error. Note that
  325. * all entries are allocated on the heap.
  326. *
  327. * @see cvmx_fdt_free_i2c_bus()
  328. */
  329. struct cvmx_fdt_i2c_bus_info *cvmx_fdt_get_i2c_bus(const void *fdt_addr, int of_offset);
  330. /**
  331. * Return the Octeon bus number for a bus descriptor
  332. *
  333. * @param[in] bus bus descriptor
  334. *
  335. * Return: Octeon twsi bus number or -1 on error
  336. */
  337. int cvmx_fdt_i2c_get_root_bus(const struct cvmx_fdt_i2c_bus_info *bus);
  338. /**
  339. * Frees all entries for an i2c bus descriptor
  340. *
  341. * @param bus bus to free
  342. *
  343. * Return: 0
  344. */
  345. int cvmx_fdt_free_i2c_bus(struct cvmx_fdt_i2c_bus_info *bus);
  346. /**
  347. * Given the bus to a device, enable it.
  348. *
  349. * @param[in] bus i2c bus descriptor to enable or disable
  350. * @param enable set to true to enable, false to disable
  351. *
  352. * Return: 0 for success or -1 for invalid bus
  353. *
  354. * This enables the entire bus including muxes and switches in the path.
  355. */
  356. int cvmx_fdt_enable_i2c_bus(const struct cvmx_fdt_i2c_bus_info *bus, bool enable);
  357. /**
  358. * Return a GPIO handle given a GPIO phandle of the form <&gpio pin flags>
  359. *
  360. * @param[in] fdt_addr Address of flat device tree
  361. * @param of_offset node offset for property
  362. * @param prop_name name of property
  363. *
  364. * Return: pointer to GPIO handle or NULL if error
  365. */
  366. struct cvmx_fdt_gpio_info *cvmx_fdt_gpio_get_info_phandle(const void *fdt_addr, int of_offset,
  367. const char *prop_name);
  368. /**
  369. * Sets a GPIO pin given the GPIO descriptor
  370. *
  371. * @param pin GPIO pin descriptor
  372. * @param value value to set it to, 0 or 1
  373. *
  374. * Return: 0 on success, -1 on error.
  375. *
  376. * NOTE: If the CVMX_GPIO_ACTIVE_LOW flag is set then the output value will be
  377. * inverted.
  378. */
  379. int cvmx_fdt_gpio_set(struct cvmx_fdt_gpio_info *pin, int value);
  380. /**
  381. * Given a GPIO pin descriptor, input the value of that pin
  382. *
  383. * @param pin GPIO pin descriptor
  384. *
  385. * Return: 0 if low, 1 if high, -1 on error. Note that the input will be
  386. * inverted if the CVMX_GPIO_ACTIVE_LOW flag bit is set.
  387. */
  388. int cvmx_fdt_gpio_get(struct cvmx_fdt_gpio_info *pin);
  389. /**
  390. * Assigns an IPD port to a SFP slot
  391. *
  392. * @param sfp Handle to SFP data structure
  393. * @param ipd_port Port to assign it to
  394. *
  395. * Return: 0 for success, -1 on error
  396. */
  397. int cvmx_sfp_set_ipd_port(struct cvmx_fdt_sfp_info *sfp, int ipd_port);
  398. /**
  399. * Get the IPD port of a SFP slot
  400. *
  401. * @param[in] sfp Handle to SFP data structure
  402. *
  403. * Return: IPD port number for SFP slot
  404. */
  405. static inline int cvmx_sfp_get_ipd_port(const struct cvmx_fdt_sfp_info *sfp)
  406. {
  407. return sfp->ipd_port[0];
  408. }
  409. /**
  410. * Get the IPD ports for a QSFP port
  411. *
  412. * @param[in] sfp Handle to SFP data structure
  413. * @param[out] ipd_ports IPD ports for each lane, if running as 40G then
  414. * only ipd_ports[0] is valid and the others will
  415. * be set to -1.
  416. */
  417. static inline void cvmx_qsfp_get_ipd_ports(const struct cvmx_fdt_sfp_info *sfp, int ipd_ports[4])
  418. {
  419. int i;
  420. for (i = 0; i < 4; i++)
  421. ipd_ports[i] = sfp->ipd_port[i];
  422. }
  423. /**
  424. * Attaches a PHY to a SFP or QSFP.
  425. *
  426. * @param sfp sfp to attach PHY to
  427. * @param phy_info phy descriptor to attach or NULL to detach
  428. */
  429. void cvmx_sfp_attach_phy(struct cvmx_fdt_sfp_info *sfp, struct cvmx_phy_info *phy_info);
  430. /**
  431. * Returns a phy descriptor for a SFP slot
  432. *
  433. * @param[in] sfp SFP to get phy info from
  434. *
  435. * Return: phy descriptor or NULL if none.
  436. */
  437. static inline struct cvmx_phy_info *cvmx_sfp_get_phy_info(const struct cvmx_fdt_sfp_info *sfp)
  438. {
  439. return sfp->phy_info;
  440. }
  441. /**
  442. * @INTERNAL
  443. * Parses all instances of the Vitesse VSC7224 reclocking chip
  444. *
  445. * @param[in] fdt_addr Address of flat device tree
  446. *
  447. * Return: 0 for success, error otherwise
  448. */
  449. int __cvmx_fdt_parse_vsc7224(const void *fdt_addr);
  450. /**
  451. * @INTERNAL
  452. * Parses all instances of the Avago AVSP5410 gearbox phy
  453. *
  454. * @param[in] fdt_addr Address of flat device tree
  455. *
  456. * Return: 0 for success, error otherwise
  457. */
  458. int __cvmx_fdt_parse_avsp5410(const void *fdt_addr);
  459. /**
  460. * Parse SFP information from device tree
  461. *
  462. * @param[in] fdt_addr Address of flat device tree
  463. *
  464. * Return: pointer to sfp info or NULL if error
  465. */
  466. struct cvmx_fdt_sfp_info *cvmx_helper_fdt_parse_sfp_info(const void *fdt_addr, int of_offset);
  467. /**
  468. * @INTERNAL
  469. * Parses either a CS4343 phy or a slice of the phy from the device tree
  470. * @param[in] fdt_addr Address of FDT
  471. * @param of_offset offset of slice or phy in device tree
  472. * @param phy_info phy_info data structure to fill in
  473. *
  474. * Return: 0 for success, -1 on error
  475. */
  476. int cvmx_fdt_parse_cs4343(const void *fdt_addr, int of_offset, struct cvmx_phy_info *phy_info);
  477. /**
  478. * Given an i2c bus and device address, write an 8 bit value
  479. *
  480. * @param bus i2c bus number
  481. * @param addr i2c device address (7 bits)
  482. * @param val 8-bit value to write
  483. *
  484. * This is just an abstraction to ease support in both U-Boot and SE.
  485. */
  486. void cvmx_fdt_i2c_reg_write(int bus, int addr, u8 val);
  487. /**
  488. * Read an 8-bit value from an i2c bus and device address
  489. *
  490. * @param bus i2c bus number
  491. * @param addr i2c device address (7 bits)
  492. *
  493. * Return: 8-bit value or error if negative
  494. */
  495. int cvmx_fdt_i2c_reg_read(int bus, int addr);
  496. /**
  497. * Write an 8-bit value to a register indexed i2c device
  498. *
  499. * @param bus i2c bus number to write to
  500. * @param addr i2c device address (7 bits)
  501. * @param reg i2c 8-bit register address
  502. * @param val 8-bit value to write
  503. *
  504. * Return: 0 for success, otherwise error
  505. */
  506. int cvmx_fdt_i2c_write8(int bus, int addr, int reg, u8 val);
  507. /**
  508. * Read an 8-bit value from a register indexed i2c device
  509. *
  510. * @param bus i2c bus number to write to
  511. * @param addr i2c device address (7 bits)
  512. * @param reg i2c 8-bit register address
  513. *
  514. * Return: value or error if negative
  515. */
  516. int cvmx_fdt_i2c_read8(int bus, int addr, int reg);
  517. int cvmx_sfp_vsc7224_mod_abs_changed(struct cvmx_fdt_sfp_info *sfp_info,
  518. int val, void *data);
  519. int cvmx_sfp_avsp5410_mod_abs_changed(struct cvmx_fdt_sfp_info *sfp_info,
  520. int val, void *data);
  521. #endif /* CVMX_HELPER_FDT_H__ */