162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Marvell 88E6xxx Switch Hidden Registers support 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2008 Marvell Semiconductor 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (c) 2019 Andrew Lunn <andrew@lunn.ch> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/bitfield.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "chip.h" 1362306a36Sopenharmony_ci#include "port.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* The mv88e6390 and mv88e6341 have some hidden registers used for debug and 1662306a36Sopenharmony_ci * development. The errata also makes use of them. 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_ciint mv88e6xxx_port_hidden_write(struct mv88e6xxx_chip *chip, int block, 1962306a36Sopenharmony_ci int port, int reg, u16 val) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci u16 ctrl; 2262306a36Sopenharmony_ci int err; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci err = mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_DATA_PORT, 2562306a36Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A, val); 2662306a36Sopenharmony_ci if (err) 2762306a36Sopenharmony_ci return err; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci ctrl = MV88E6XXX_PORT_RESERVED_1A_BUSY | 3062306a36Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A_WRITE | 3162306a36Sopenharmony_ci block << MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT | 3262306a36Sopenharmony_ci port << MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT | 3362306a36Sopenharmony_ci reg; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci return mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT, 3662306a36Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A, ctrl); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ciint mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci int bit = __bf_shf(MV88E6XXX_PORT_RESERVED_1A_BUSY); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci return mv88e6xxx_port_wait_bit(chip, 4462306a36Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT, 4562306a36Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A, bit, 0); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciint mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port, 4962306a36Sopenharmony_ci int reg, u16 *val) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci u16 ctrl; 5262306a36Sopenharmony_ci int err; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci ctrl = MV88E6XXX_PORT_RESERVED_1A_BUSY | 5562306a36Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A_READ | 5662306a36Sopenharmony_ci block << MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT | 5762306a36Sopenharmony_ci port << MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT | 5862306a36Sopenharmony_ci reg; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci err = mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT, 6162306a36Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A, ctrl); 6262306a36Sopenharmony_ci if (err) 6362306a36Sopenharmony_ci return err; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci err = mv88e6xxx_port_hidden_wait(chip); 6662306a36Sopenharmony_ci if (err) 6762306a36Sopenharmony_ci return err; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci return mv88e6xxx_port_read(chip, MV88E6XXX_PORT_RESERVED_1A_DATA_PORT, 7062306a36Sopenharmony_ci MV88E6XXX_PORT_RESERVED_1A, val); 7162306a36Sopenharmony_ci} 72