diff options
Diffstat (limited to 'arch/mips/mach-octeon/include/mach/cvmx-helper-fdt.h')
-rw-r--r-- | arch/mips/mach-octeon/include/mach/cvmx-helper-fdt.h | 568 |
1 files changed, 568 insertions, 0 deletions
diff --git a/arch/mips/mach-octeon/include/mach/cvmx-helper-fdt.h b/arch/mips/mach-octeon/include/mach/cvmx-helper-fdt.h new file mode 100644 index 0000000000..d3809aec29 --- /dev/null +++ b/arch/mips/mach-octeon/include/mach/cvmx-helper-fdt.h @@ -0,0 +1,568 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 Marvell International Ltd. + * + * FDT Helper functions similar to those provided to U-Boot. + * If compiled for U-Boot, just provide wrappers to the equivalent U-Boot + * functions. + */ + +#ifndef __CVMX_HELPER_FDT_H__ +#define __CVMX_HELPER_FDT_H__ + +#include <fdt_support.h> +#include <fdtdec.h> +#include <time.h> +#include <asm/global_data.h> +#include <linux/libfdt.h> + +#include <mach/cvmx-helper-sfp.h> + +enum cvmx_i2c_bus_type { + CVMX_I2C_BUS_OCTEON, + CVMX_I2C_MUX_PCA9540, + CVMX_I2C_MUX_PCA9542, + CVMX_I2C_MUX_PCA9543, + CVMX_I2C_MUX_PCA9544, + CVMX_I2C_MUX_PCA9545, + CVMX_I2C_MUX_PCA9546, + CVMX_I2C_MUX_PCA9547, + CVMX_I2C_MUX_PCA9548, + CVMX_I2C_MUX_OTHER +}; + +struct cvmx_sfp_mod_info; /** Defined in cvmx-helper-sfp.h */ +struct cvmx_phy_info; /** Defined in cvmx-helper-board.h */ + +/** + * This data structure holds information about various I2C muxes and switches + * that may be between a device and the Octeon chip. + */ +struct cvmx_fdt_i2c_bus_info { + /** Parent I2C bus, NULL if root */ + struct cvmx_fdt_i2c_bus_info *parent; + /** Child I2C bus or NULL if last entry in the chain */ + struct cvmx_fdt_i2c_bus_info *child; + /** Offset in device tree */ + int of_offset; + /** Type of i2c bus or mux */ + enum cvmx_i2c_bus_type type; + /** I2C address of mux */ + u8 i2c_addr; + /** Mux channel number */ + u8 channel; + /** For muxes, the bit(s) to set to enable them */ + u8 enable_bit; + /** True if mux, false if switch */ + bool is_mux; +}; + +/** + * Data structure containing information about SFP/QSFP slots + */ +struct cvmx_fdt_sfp_info { + /** Used for a linked list of slots */ + struct cvmx_fdt_sfp_info *next, *prev; + /** Used when multiple SFP ports share the same IPD port */ + struct cvmx_fdt_sfp_info *next_iface_sfp; + /** Name from device tree of slot */ + const char *name; + /** I2C bus for slot EEPROM */ + struct cvmx_fdt_i2c_bus_info *i2c_bus; + /** Data from SFP or QSFP EEPROM */ + struct cvmx_sfp_mod_info sfp_info; + /** Data structure with PHY information */ + struct cvmx_phy_info *phy_info; + /** IPD port(s) slot is connected to */ + int ipd_port[4]; + /** Offset in device tree of slot */ + int of_offset; + /** EEPROM address of SFP module (usually 0x50) */ + u8 i2c_eeprom_addr; + /** Diagnostic address of SFP module (usually 0x51) */ + u8 i2c_diag_addr; + /** True if QSFP module */ + bool is_qsfp; + /** True if EEPROM data is valid */ + bool valid; + /** SFP tx_disable GPIO descriptor */ + struct cvmx_fdt_gpio_info *tx_disable; + /** SFP mod_abs/QSFP mod_prs GPIO descriptor */ + struct cvmx_fdt_gpio_info *mod_abs; + /** SFP tx_error GPIO descriptor */ + struct cvmx_fdt_gpio_info *tx_error; + /** SFP rx_los GPIO discriptor */ + struct cvmx_fdt_gpio_info *rx_los; + /** QSFP select GPIO descriptor */ + struct cvmx_fdt_gpio_info *select; + /** QSFP reset GPIO descriptor */ + struct cvmx_fdt_gpio_info *reset; + /** QSFP interrupt GPIO descriptor */ + struct cvmx_fdt_gpio_info *interrupt; + /** QSFP lp_mode GPIO descriptor */ + struct cvmx_fdt_gpio_info *lp_mode; + /** Last mod_abs value */ + int last_mod_abs; + /** Last rx_los value */ + int last_rx_los; + /** Function to call to check mod_abs */ + int (*check_mod_abs)(struct cvmx_fdt_sfp_info *sfp_info, void *data); + /** User-defined data to pass to check_mod_abs */ + void *mod_abs_data; + /** Function to call when mod_abs changes */ + int (*mod_abs_changed)(struct cvmx_fdt_sfp_info *sfp_info, int val, void *data); + /** User-defined data to pass to mod_abs_changed */ + void *mod_abs_changed_data; + /** Function to call when rx_los changes */ + int (*rx_los_changed)(struct cvmx_fdt_sfp_info *sfp_info, int val, void *data); + /** User-defined data to pass to rx_los_changed */ + void *rx_los_changed_data; + /** True if we're connected to a Microsemi VSC7224 reclocking chip */ + bool is_vsc7224; + /** Data structure for first vsc7224 channel we're attached to */ + struct cvmx_vsc7224_chan *vsc7224_chan; + /** True if we're connected to a Avago AVSP5410 phy */ + bool is_avsp5410; + /** Data structure for avsp5410 phy we're attached to */ + struct cvmx_avsp5410 *avsp5410; + /** xinterface we're on */ + int xiface; + /** port index */ + int index; +}; + +/** + * Look up a phandle and follow it to its node then return the offset of that + * node. + * + * @param[in] fdt_addr pointer to FDT blob + * @param node node to read phandle from + * @param[in] prop_name name of property to find + * @param[in,out] lenp Number of phandles, input max number + * @param[out] nodes Array of phandle nodes + * + * @return -ve error code on error or 0 for success + */ +int cvmx_fdt_lookup_phandles(const void *fdt_addr, int node, const char *prop_name, int *lenp, + int *nodes); + +/** + * Helper to return the address property + * + * @param[in] fdt_addr pointer to FDT blob + * @param node node to read address from + * @param prop_name property name to read + * + * @return address of property or FDT_ADDR_T_NONE if not found + */ +static inline fdt_addr_t cvmx_fdt_get_addr(const void *fdt_addr, int node, const char *prop_name) +{ + return fdtdec_get_addr(fdt_addr, node, prop_name); +} + +/** + * Helper function to return an integer property + * + * @param[in] fdt_addr pointer to FDT blob + * @param node node to read integer from + * @param[in] prop_name property name to read + * @param default_val default value to return if property doesn't exist + * + * @return integer value of property or default_val if it doesn't exist. + */ +static inline int cvmx_fdt_get_int(const void *fdt_addr, int node, const char *prop_name, + int default_val) +{ + return fdtdec_get_int(fdt_addr, node, prop_name, default_val); +} + +static inline bool cvmx_fdt_get_bool(const void *fdt_addr, int node, const char *prop_name) +{ + return fdtdec_get_bool(fdt_addr, node, prop_name); +} + +static inline u64 cvmx_fdt_get_uint64(const void *fdt_addr, int node, const char *prop_name, + u64 default_val) +{ + return fdtdec_get_uint64(fdt_addr, node, prop_name, default_val); +} + +/** + * Look up a phandle and follow it to its node then return the offset of that + * node. + * + * @param[in] fdt_addr pointer to FDT blob + * @param node node to read phandle from + * @param[in] prop_name name of property to find + * + * @return node offset if found, -ve error code on error + */ +static inline int cvmx_fdt_lookup_phandle(const void *fdt_addr, int node, const char *prop_name) +{ + return fdtdec_lookup_phandle(fdt_addr, node, prop_name); +} + +/** + * Translate an address from the device tree into a CPU physical address by + * walking up the device tree and applying bus mappings along the way. + * + * This uses #size-cells and #address-cells. + * + * @param[in] fdt_addr Address of flat device tree + * @param node node to start translating from + * @param[in] in_addr Address to translate + * NOTE: in_addr must be in the native ENDIAN + * format. + * + * @return Translated address or FDT_ADDR_T_NONE if address cannot be + * translated. + */ +static inline u64 cvmx_fdt_translate_address(const void *fdt_addr, int node, const u32 *in_addr) +{ + return fdt_translate_address((void *)fdt_addr, node, in_addr); +} + +/** + * Compare compatibile strings in the flat device tree. + * + * @param[in] s1 First string to compare + * @param[in] sw Second string to compare + * + * @return 0 if no match + * 1 if only the part number matches and not the manufacturer + * 2 if both the part number and manufacturer match + */ +int cvmx_fdt_compat_match(const char *s1, const char *s2); + +/** + * Returns whether a list of strings contains the specified string + * + * @param[in] slist String list + * @param llen string list total length + * @param[in] str string to search for + * + * @return 1 if string list contains string, 0 if it does not. + */ +int cvmx_fdt_compat_list_contains(const char *slist, int llen, const char *str); + +/** + * Check if a node is compatible with the specified compat string + * + * @param[in] fdt_addr FDT address + * @param node node offset to check + * @param[in] compat compatible string to check + * + * @return 0 if compatible, 1 if not compatible, error if negative + */ +int cvmx_fdt_node_check_compatible(const void *fdt_addr, int node, const char *compat); + +/** + * @INTERNAL + * Compares a string to a compatible field. + * + * @param[in] compat compatible string + * @param[in] str string to check + * + * @return 0 if not compatible, 1 if manufacturer compatible, 2 if + * part is compatible, 3 if both part and manufacturer are + * compatible. + */ +int __cvmx_fdt_compat_match(const char *compat, const char *str); + +/** + * Given a phandle to a GPIO device return the type of GPIO device it is. + * + * @param[in] fdt_addr Address of flat device tree + * @param phandle phandle to GPIO + * @param[out] size Number of pins (optional, may be NULL) + * + * @return Type of GPIO device or PIN_ERROR if error + */ +enum cvmx_gpio_type cvmx_fdt_get_gpio_type(const void *fdt_addr, int phandle, int *size); + +/** + * Given a phandle to a GPIO node output the i2c bus and address + * + * @param[in] fdt_addr Address of FDT + * @param phandle phandle of GPIO device + * @param[out] bus TWSI bus number with node in bits 1-3, can be + * NULL for none. + * @param[out] addr TWSI address number, can be NULL for none + * + * @return 0 for success, error otherwise + */ +int cvmx_fdt_get_twsi_gpio_bus_addr(const void *fdt_addr, int phandle, int *bus, int *addr); + +/** + * Given a FDT node return the CPU node number + * + * @param[in] fdt_addr Address of FDT + * @param node FDT node number + * + * @return CPU node number or error if negative + */ +int cvmx_fdt_get_cpu_node(const void *fdt_addr, int node); + +/** + * Get the total size of the flat device tree + * + * @param[in] fdt_addr Address of FDT + * + * @return Size of flat device tree in bytes or -1 if error. + */ +int cvmx_fdt_get_fdt_size(const void *fdt_addr); + +/** + * Returns if a node is compatible with one of the items in the string list + * + * @param[in] fdt_addr Pointer to flat device tree + * @param node Node offset to check + * @param[in] strlist Array of FDT device compatibility strings, + * must end with NULL or empty string. + * + * @return 0 if at least one item matches, 1 if no matches + */ +int cvmx_fdt_node_check_compatible_list(const void *fdt_addr, int node, const char *const *strlist); + +/** + * Given a FDT node, return the next compatible node. + * + * @param[in] fdt_addr Pointer to flat device tree + * @param start_offset Starting node offset or -1 to find the first + * @param strlist Array of FDT device compatibility strings, must + * end with NULL or empty string. + * + * @return next matching node or -1 if no more matches. + */ +int cvmx_fdt_node_offset_by_compatible_list(const void *fdt_addr, int startoffset, + const char *const *strlist); + +/** + * Given the parent offset of an i2c device build up a list describing the bus + * which can contain i2c muxes and switches. + * + * @param[in] fdt_addr address of device tree + * @param of_offset Offset of the parent node of a GPIO device in + * the device tree. + * + * @return pointer to list of i2c devices starting from the root which + * can include i2c muxes and switches or NULL if error. Note that + * all entries are allocated on the heap. + * + * @see cvmx_fdt_free_i2c_bus() + */ +struct cvmx_fdt_i2c_bus_info *cvmx_fdt_get_i2c_bus(const void *fdt_addr, int of_offset); + +/** + * Return the Octeon bus number for a bus descriptor + * + * @param[in] bus bus descriptor + * + * @return Octeon twsi bus number or -1 on error + */ +int cvmx_fdt_i2c_get_root_bus(const struct cvmx_fdt_i2c_bus_info *bus); + +/** + * Frees all entries for an i2c bus descriptor + * + * @param bus bus to free + * + * @return 0 + */ +int cvmx_fdt_free_i2c_bus(struct cvmx_fdt_i2c_bus_info *bus); + +/** + * Given the bus to a device, enable it. + * + * @param[in] bus i2c bus descriptor to enable or disable + * @param enable set to true to enable, false to disable + * + * @return 0 for success or -1 for invalid bus + * + * This enables the entire bus including muxes and switches in the path. + */ +int cvmx_fdt_enable_i2c_bus(const struct cvmx_fdt_i2c_bus_info *bus, bool enable); + +/** + * Return a GPIO handle given a GPIO phandle of the form <&gpio pin flags> + * + * @param[in] fdt_addr Address of flat device tree + * @param of_offset node offset for property + * @param prop_name name of property + * + * @return pointer to GPIO handle or NULL if error + */ +struct cvmx_fdt_gpio_info *cvmx_fdt_gpio_get_info_phandle(const void *fdt_addr, int of_offset, + const char *prop_name); + +/** + * Sets a GPIO pin given the GPIO descriptor + * + * @param pin GPIO pin descriptor + * @param value value to set it to, 0 or 1 + * + * @return 0 on success, -1 on error. + * + * NOTE: If the CVMX_GPIO_ACTIVE_LOW flag is set then the output value will be + * inverted. + */ +int cvmx_fdt_gpio_set(struct cvmx_fdt_gpio_info *pin, int value); + +/** + * Given a GPIO pin descriptor, input the value of that pin + * + * @param pin GPIO pin descriptor + * + * @return 0 if low, 1 if high, -1 on error. Note that the input will be + * inverted if the CVMX_GPIO_ACTIVE_LOW flag bit is set. + */ +int cvmx_fdt_gpio_get(struct cvmx_fdt_gpio_info *pin); + +/** + * Assigns an IPD port to a SFP slot + * + * @param sfp Handle to SFP data structure + * @param ipd_port Port to assign it to + * + * @return 0 for success, -1 on error + */ +int cvmx_sfp_set_ipd_port(struct cvmx_fdt_sfp_info *sfp, int ipd_port); + +/** + * Get the IPD port of a SFP slot + * + * @param[in] sfp Handle to SFP data structure + * + * @return IPD port number for SFP slot + */ +static inline int cvmx_sfp_get_ipd_port(const struct cvmx_fdt_sfp_info *sfp) +{ + return sfp->ipd_port[0]; +} + +/** + * Get the IPD ports for a QSFP port + * + * @param[in] sfp Handle to SFP data structure + * @param[out] ipd_ports IPD ports for each lane, if running as 40G then + * only ipd_ports[0] is valid and the others will + * be set to -1. + */ +static inline void cvmx_qsfp_get_ipd_ports(const struct cvmx_fdt_sfp_info *sfp, int ipd_ports[4]) +{ + int i; + + for (i = 0; i < 4; i++) + ipd_ports[i] = sfp->ipd_port[i]; +} + +/** + * Attaches a PHY to a SFP or QSFP. + * + * @param sfp sfp to attach PHY to + * @param phy_info phy descriptor to attach or NULL to detach + */ +void cvmx_sfp_attach_phy(struct cvmx_fdt_sfp_info *sfp, struct cvmx_phy_info *phy_info); + +/** + * Returns a phy descriptor for a SFP slot + * + * @param[in] sfp SFP to get phy info from + * + * @return phy descriptor or NULL if none. + */ +static inline struct cvmx_phy_info *cvmx_sfp_get_phy_info(const struct cvmx_fdt_sfp_info *sfp) +{ + return sfp->phy_info; +} + +/** + * @INTERNAL + * Parses all instances of the Vitesse VSC7224 reclocking chip + * + * @param[in] fdt_addr Address of flat device tree + * + * @return 0 for success, error otherwise + */ +int __cvmx_fdt_parse_vsc7224(const void *fdt_addr); + +/** + * @INTERNAL + * Parses all instances of the Avago AVSP5410 gearbox phy + * + * @param[in] fdt_addr Address of flat device tree + * + * @return 0 for success, error otherwise + */ +int __cvmx_fdt_parse_avsp5410(const void *fdt_addr); + +/** + * Parse SFP information from device tree + * + * @param[in] fdt_addr Address of flat device tree + * + * @return pointer to sfp info or NULL if error + */ +struct cvmx_fdt_sfp_info *cvmx_helper_fdt_parse_sfp_info(const void *fdt_addr, int of_offset); + +/** + * @INTERNAL + * Parses either a CS4343 phy or a slice of the phy from the device tree + * @param[in] fdt_addr Address of FDT + * @param of_offset offset of slice or phy in device tree + * @param phy_info phy_info data structure to fill in + * + * @return 0 for success, -1 on error + */ +int cvmx_fdt_parse_cs4343(const void *fdt_addr, int of_offset, struct cvmx_phy_info *phy_info); + +/** + * Given an i2c bus and device address, write an 8 bit value + * + * @param bus i2c bus number + * @param addr i2c device address (7 bits) + * @param val 8-bit value to write + * + * This is just an abstraction to ease support in both U-Boot and SE. + */ +void cvmx_fdt_i2c_reg_write(int bus, int addr, u8 val); + +/** + * Read an 8-bit value from an i2c bus and device address + * + * @param bus i2c bus number + * @param addr i2c device address (7 bits) + * + * @return 8-bit value or error if negative + */ +int cvmx_fdt_i2c_reg_read(int bus, int addr); + +/** + * Write an 8-bit value to a register indexed i2c device + * + * @param bus i2c bus number to write to + * @param addr i2c device address (7 bits) + * @param reg i2c 8-bit register address + * @param val 8-bit value to write + * + * @return 0 for success, otherwise error + */ +int cvmx_fdt_i2c_write8(int bus, int addr, int reg, u8 val); + +/** + * Read an 8-bit value from a register indexed i2c device + * + * @param bus i2c bus number to write to + * @param addr i2c device address (7 bits) + * @param reg i2c 8-bit register address + * + * @return value or error if negative + */ +int cvmx_fdt_i2c_read8(int bus, int addr, int reg); + +int cvmx_sfp_vsc7224_mod_abs_changed(struct cvmx_fdt_sfp_info *sfp_info, + int val, void *data); +int cvmx_sfp_avsp5410_mod_abs_changed(struct cvmx_fdt_sfp_info *sfp_info, + int val, void *data); + +#endif /* CVMX_HELPER_FDT_H__ */ |