cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

global2_scratch.c (7697B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Marvell 88E6xxx Switch Global 2 Scratch & Misc Registers support
      4 *
      5 * Copyright (c) 2008 Marvell Semiconductor
      6 *
      7 * Copyright (c) 2017 National Instruments
      8 *      Brandon Streiff <brandon.streiff@ni.com>
      9 */
     10
     11#include "chip.h"
     12#include "global2.h"
     13
     14/* Offset 0x1A: Scratch and Misc. Register */
     15static int mv88e6xxx_g2_scratch_read(struct mv88e6xxx_chip *chip, int reg,
     16				     u8 *data)
     17{
     18	u16 value;
     19	int err;
     20
     21	err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC,
     22				 reg << 8);
     23	if (err)
     24		return err;
     25
     26	err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC, &value);
     27	if (err)
     28		return err;
     29
     30	*data = (value & MV88E6XXX_G2_SCRATCH_MISC_DATA_MASK);
     31
     32	return 0;
     33}
     34
     35static int mv88e6xxx_g2_scratch_write(struct mv88e6xxx_chip *chip, int reg,
     36				      u8 data)
     37{
     38	u16 value = (reg << 8) | data;
     39
     40	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC,
     41				  MV88E6XXX_G2_SCRATCH_MISC_UPDATE | value);
     42}
     43
     44/**
     45 * mv88e6xxx_g2_scratch_get_bit - get a bit
     46 * @chip: chip private data
     47 * @base_reg: base of scratch bits
     48 * @offset: index of bit within the register
     49 * @set: is bit set?
     50 */
     51static int mv88e6xxx_g2_scratch_get_bit(struct mv88e6xxx_chip *chip,
     52					int base_reg, unsigned int offset,
     53					int *set)
     54{
     55	int reg = base_reg + (offset / 8);
     56	u8 mask = (1 << (offset & 0x7));
     57	u8 val;
     58	int err;
     59
     60	err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
     61	if (err)
     62		return err;
     63
     64	*set = !!(mask & val);
     65
     66	return 0;
     67}
     68
     69/**
     70 * mv88e6xxx_g2_scratch_set_bit - set (or clear) a bit
     71 * @chip: chip private data
     72 * @base_reg: base of scratch bits
     73 * @offset: index of bit within the register
     74 * @set: should this bit be set?
     75 *
     76 * Helper function for dealing with the direction and data registers.
     77 */
     78static int mv88e6xxx_g2_scratch_set_bit(struct mv88e6xxx_chip *chip,
     79					int base_reg, unsigned int offset,
     80					int set)
     81{
     82	int reg = base_reg + (offset / 8);
     83	u8 mask = (1 << (offset & 0x7));
     84	u8 val;
     85	int err;
     86
     87	err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
     88	if (err)
     89		return err;
     90
     91	if (set)
     92		val |= mask;
     93	else
     94		val &= ~mask;
     95
     96	return mv88e6xxx_g2_scratch_write(chip, reg, val);
     97}
     98
     99/**
    100 * mv88e6352_g2_scratch_gpio_get_data - get data on gpio pin
    101 * @chip: chip private data
    102 * @pin: gpio index
    103 *
    104 * Return: 0 for low, 1 for high, negative error
    105 */
    106static int mv88e6352_g2_scratch_gpio_get_data(struct mv88e6xxx_chip *chip,
    107					      unsigned int pin)
    108{
    109	int val = 0;
    110	int err;
    111
    112	err = mv88e6xxx_g2_scratch_get_bit(chip,
    113					   MV88E6352_G2_SCRATCH_GPIO_DATA0,
    114					   pin, &val);
    115	if (err)
    116		return err;
    117
    118	return val;
    119}
    120
    121/**
    122 * mv88e6352_g2_scratch_gpio_set_data - set data on gpio pin
    123 * @chip: chip private data
    124 * @pin: gpio index
    125 * @value: value to set
    126 */
    127static int mv88e6352_g2_scratch_gpio_set_data(struct mv88e6xxx_chip *chip,
    128					      unsigned int pin, int value)
    129{
    130	u8 mask = (1 << (pin & 0x7));
    131	int offset = (pin / 8);
    132	int reg;
    133
    134	reg = MV88E6352_G2_SCRATCH_GPIO_DATA0 + offset;
    135
    136	if (value)
    137		chip->gpio_data[offset] |= mask;
    138	else
    139		chip->gpio_data[offset] &= ~mask;
    140
    141	return mv88e6xxx_g2_scratch_write(chip, reg, chip->gpio_data[offset]);
    142}
    143
    144/**
    145 * mv88e6352_g2_scratch_gpio_get_dir - get direction of gpio pin
    146 * @chip: chip private data
    147 * @pin: gpio index
    148 *
    149 * Return: 0 for output, 1 for input (same as GPIOF_DIR_XXX).
    150 */
    151static int mv88e6352_g2_scratch_gpio_get_dir(struct mv88e6xxx_chip *chip,
    152					     unsigned int pin)
    153{
    154	int val = 0;
    155	int err;
    156
    157	err = mv88e6xxx_g2_scratch_get_bit(chip,
    158					   MV88E6352_G2_SCRATCH_GPIO_DIR0,
    159					   pin, &val);
    160	if (err)
    161		return err;
    162
    163	return val;
    164}
    165
    166/**
    167 * mv88e6352_g2_scratch_gpio_set_dir - set direction of gpio pin
    168 * @chip: chip private data
    169 * @pin: gpio index
    170 * @input: should the gpio be an input, or an output?
    171 */
    172static int mv88e6352_g2_scratch_gpio_set_dir(struct mv88e6xxx_chip *chip,
    173					     unsigned int pin, bool input)
    174{
    175	int value = (input ? MV88E6352_G2_SCRATCH_GPIO_DIR_IN :
    176			     MV88E6352_G2_SCRATCH_GPIO_DIR_OUT);
    177
    178	return mv88e6xxx_g2_scratch_set_bit(chip,
    179					    MV88E6352_G2_SCRATCH_GPIO_DIR0,
    180					    pin, value);
    181}
    182
    183/**
    184 * mv88e6352_g2_scratch_gpio_get_pctl - get pin control setting
    185 * @chip: chip private data
    186 * @pin: gpio index
    187 * @func: function number
    188 *
    189 * Note that the function numbers themselves may vary by chipset.
    190 */
    191static int mv88e6352_g2_scratch_gpio_get_pctl(struct mv88e6xxx_chip *chip,
    192					      unsigned int pin, int *func)
    193{
    194	int reg = MV88E6352_G2_SCRATCH_GPIO_PCTL0 + (pin / 2);
    195	int offset = (pin & 0x1) ? 4 : 0;
    196	u8 mask = (0x7 << offset);
    197	int err;
    198	u8 val;
    199
    200	err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
    201	if (err)
    202		return err;
    203
    204	*func = (val & mask) >> offset;
    205
    206	return 0;
    207}
    208
    209/**
    210 * mv88e6352_g2_scratch_gpio_set_pctl - set pin control setting
    211 * @chip: chip private data
    212 * @pin: gpio index
    213 * @func: function number
    214 */
    215static int mv88e6352_g2_scratch_gpio_set_pctl(struct mv88e6xxx_chip *chip,
    216					      unsigned int pin, int func)
    217{
    218	int reg = MV88E6352_G2_SCRATCH_GPIO_PCTL0 + (pin / 2);
    219	int offset = (pin & 0x1) ? 4 : 0;
    220	u8 mask = (0x7 << offset);
    221	int err;
    222	u8 val;
    223
    224	err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
    225	if (err)
    226		return err;
    227
    228	val = (val & ~mask) | ((func & mask) << offset);
    229
    230	return mv88e6xxx_g2_scratch_write(chip, reg, val);
    231}
    232
    233const struct mv88e6xxx_gpio_ops mv88e6352_gpio_ops = {
    234	.get_data = mv88e6352_g2_scratch_gpio_get_data,
    235	.set_data = mv88e6352_g2_scratch_gpio_set_data,
    236	.get_dir = mv88e6352_g2_scratch_gpio_get_dir,
    237	.set_dir = mv88e6352_g2_scratch_gpio_set_dir,
    238	.get_pctl = mv88e6352_g2_scratch_gpio_get_pctl,
    239	.set_pctl = mv88e6352_g2_scratch_gpio_set_pctl,
    240};
    241
    242/**
    243 * mv88e6xxx_g2_scratch_gpio_set_smi - set gpio muxing for external smi
    244 * @chip: chip private data
    245 * @external: set mux for external smi, or free for gpio usage
    246 *
    247 * Some mv88e6xxx models have GPIO pins that may be configured as
    248 * an external SMI interface, or they may be made free for other
    249 * GPIO uses.
    250 */
    251int mv88e6xxx_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip *chip,
    252				      bool external)
    253{
    254	int misc_cfg = MV88E6352_G2_SCRATCH_MISC_CFG;
    255	int config_data1 = MV88E6352_G2_SCRATCH_CONFIG_DATA1;
    256	int config_data2 = MV88E6352_G2_SCRATCH_CONFIG_DATA2;
    257	bool no_cpu;
    258	u8 p0_mode;
    259	int err;
    260	u8 val;
    261
    262	err = mv88e6xxx_g2_scratch_read(chip, config_data2, &val);
    263	if (err)
    264		return err;
    265
    266	p0_mode = val & MV88E6352_G2_SCRATCH_CONFIG_DATA2_P0_MODE_MASK;
    267
    268	if (p0_mode == 0x01 || p0_mode == 0x02)
    269		return -EBUSY;
    270
    271	err = mv88e6xxx_g2_scratch_read(chip, config_data1, &val);
    272	if (err)
    273		return err;
    274
    275	no_cpu = !!(val & MV88E6352_G2_SCRATCH_CONFIG_DATA1_NO_CPU);
    276
    277	err = mv88e6xxx_g2_scratch_read(chip, misc_cfg, &val);
    278	if (err)
    279		return err;
    280
    281	/* NO_CPU being 0 inverts the meaning of the bit */
    282	if (!no_cpu)
    283		external = !external;
    284
    285	if (external)
    286		val |= MV88E6352_G2_SCRATCH_MISC_CFG_NORMALSMI;
    287	else
    288		val &= ~MV88E6352_G2_SCRATCH_MISC_CFG_NORMALSMI;
    289
    290	return mv88e6xxx_g2_scratch_write(chip, misc_cfg, val);
    291}
    292
    293/**
    294 * mv88e6352_g2_scratch_port_has_serdes - indicate if a port can have a serdes
    295 * @chip: chip private data
    296 * @port: port number to check for serdes
    297 *
    298 * Indicates whether the port may have a serdes attached according to the
    299 * pin strapping. Returns negative error number, 0 if the port is not
    300 * configured to have a serdes, and 1 if the port is configured to have a
    301 * serdes attached.
    302 */
    303int mv88e6352_g2_scratch_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
    304{
    305	u8 config3, p;
    306	int err;
    307
    308	err = mv88e6xxx_g2_scratch_read(chip, MV88E6352_G2_SCRATCH_CONFIG_DATA3,
    309					&config3);
    310	if (err)
    311		return err;
    312
    313	if (config3 & MV88E6352_G2_SCRATCH_CONFIG_DATA3_S_SEL)
    314		p = 5;
    315	else
    316		p = 4;
    317
    318	return port == p;
    319}