18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Marvell 88E6xxx Switch Hidden Registers support 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2008 Marvell Semiconductor 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2019 Andrew Lunn <andrew@lunn.ch> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/bitfield.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "chip.h" 138c2ecf20Sopenharmony_ci#include "port.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci/* The mv88e6390 and mv88e6341 have some hidden registers used for debug and 168c2ecf20Sopenharmony_ci * development. The errata also makes use of them. 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ciint mv88e6xxx_port_hidden_write(struct mv88e6xxx_chip *chip, int block, 198c2ecf20Sopenharmony_ci int port, int reg, u16 val) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci u16 ctrl; 228c2ecf20Sopenharmony_ci int err; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci err = mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_DATA_PORT, 258c2ecf20Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A, val); 268c2ecf20Sopenharmony_ci if (err) 278c2ecf20Sopenharmony_ci return err; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci ctrl = MV88E6XXX_PORT_RESERVED_1A_BUSY | 308c2ecf20Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A_WRITE | 318c2ecf20Sopenharmony_ci block << MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT | 328c2ecf20Sopenharmony_ci port << MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT | 338c2ecf20Sopenharmony_ci reg; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci return mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT, 368c2ecf20Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A, ctrl); 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ciint mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci int bit = __bf_shf(MV88E6XXX_PORT_RESERVED_1A_BUSY); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci return mv88e6xxx_wait_bit(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT, 448c2ecf20Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A, bit, 0); 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ciint mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port, 488c2ecf20Sopenharmony_ci int reg, u16 *val) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci u16 ctrl; 518c2ecf20Sopenharmony_ci int err; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci ctrl = MV88E6XXX_PORT_RESERVED_1A_BUSY | 548c2ecf20Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A_READ | 558c2ecf20Sopenharmony_ci block << MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT | 568c2ecf20Sopenharmony_ci port << MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT | 578c2ecf20Sopenharmony_ci reg; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci err = mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT, 608c2ecf20Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A, ctrl); 618c2ecf20Sopenharmony_ci if (err) 628c2ecf20Sopenharmony_ci return err; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci err = mv88e6xxx_port_hidden_wait(chip); 658c2ecf20Sopenharmony_ci if (err) 668c2ecf20Sopenharmony_ci return err; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci return mv88e6xxx_port_read(chip, MV88E6XXX_PORT_RESERVED_1A_DATA_PORT, 698c2ecf20Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A, val); 708c2ecf20Sopenharmony_ci} 71