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