1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Marvell 88E6xxx Switch Global 2 Scratch & Misc Registers support
5 * Copyright (c) 2008 Marvell Semiconductor
7 * Copyright (c) 2017 National Instruments
8 * Brandon Streiff <brandon.streiff@ni.com>
14 /* Offset 0x1A: Scratch and Misc. Register */
15 static int mv88e6xxx_g2_scratch_read(struct mv88e6xxx_chip
*chip
, int reg
,
21 err
= mv88e6xxx_g2_write(chip
, MV88E6XXX_G2_SCRATCH_MISC_MISC
,
26 err
= mv88e6xxx_g2_read(chip
, MV88E6XXX_G2_SCRATCH_MISC_MISC
, &value
);
30 *data
= (value
& MV88E6XXX_G2_SCRATCH_MISC_DATA_MASK
);
35 static int mv88e6xxx_g2_scratch_write(struct mv88e6xxx_chip
*chip
, int reg
,
38 u16 value
= (reg
<< 8) | data
;
40 return mv88e6xxx_g2_write(chip
, MV88E6XXX_G2_SCRATCH_MISC_MISC
,
41 MV88E6XXX_G2_SCRATCH_MISC_UPDATE
| value
);
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
51 static int mv88e6xxx_g2_scratch_get_bit(struct mv88e6xxx_chip
*chip
,
52 int base_reg
, unsigned int offset
,
55 int reg
= base_reg
+ (offset
/ 8);
56 u8 mask
= (1 << (offset
& 0x7));
60 err
= mv88e6xxx_g2_scratch_read(chip
, reg
, &val
);
64 *set
= !!(mask
& val
);
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?
76 * Helper function for dealing with the direction and data registers.
78 static int mv88e6xxx_g2_scratch_set_bit(struct mv88e6xxx_chip
*chip
,
79 int base_reg
, unsigned int offset
,
82 int reg
= base_reg
+ (offset
/ 8);
83 u8 mask
= (1 << (offset
& 0x7));
87 err
= mv88e6xxx_g2_scratch_read(chip
, reg
, &val
);
96 return mv88e6xxx_g2_scratch_write(chip
, reg
, val
);
100 * mv88e6352_g2_scratch_gpio_get_data - get data on gpio pin
101 * @chip: chip private data
104 * Return: 0 for low, 1 for high, negative error
106 static int mv88e6352_g2_scratch_gpio_get_data(struct mv88e6xxx_chip
*chip
,
112 err
= mv88e6xxx_g2_scratch_get_bit(chip
,
113 MV88E6352_G2_SCRATCH_GPIO_DATA0
,
122 * mv88e6352_g2_scratch_gpio_set_data - set data on gpio pin
123 * @chip: chip private data
125 * @value: value to set
127 static int mv88e6352_g2_scratch_gpio_set_data(struct mv88e6xxx_chip
*chip
,
128 unsigned int pin
, int value
)
130 u8 mask
= (1 << (pin
& 0x7));
131 int offset
= (pin
/ 8);
134 reg
= MV88E6352_G2_SCRATCH_GPIO_DATA0
+ offset
;
137 chip
->gpio_data
[offset
] |= mask
;
139 chip
->gpio_data
[offset
] &= ~mask
;
141 return mv88e6xxx_g2_scratch_write(chip
, reg
, chip
->gpio_data
[offset
]);
145 * mv88e6352_g2_scratch_gpio_get_dir - get direction of gpio pin
146 * @chip: chip private data
149 * Return: 0 for output, 1 for input.
151 static int mv88e6352_g2_scratch_gpio_get_dir(struct mv88e6xxx_chip
*chip
,
157 err
= mv88e6xxx_g2_scratch_get_bit(chip
,
158 MV88E6352_G2_SCRATCH_GPIO_DIR0
,
167 * mv88e6352_g2_scratch_gpio_set_dir - set direction of gpio pin
168 * @chip: chip private data
170 * @input: should the gpio be an input, or an output?
172 static int mv88e6352_g2_scratch_gpio_set_dir(struct mv88e6xxx_chip
*chip
,
173 unsigned int pin
, bool input
)
175 int value
= (input
? MV88E6352_G2_SCRATCH_GPIO_DIR_IN
:
176 MV88E6352_G2_SCRATCH_GPIO_DIR_OUT
);
178 return mv88e6xxx_g2_scratch_set_bit(chip
,
179 MV88E6352_G2_SCRATCH_GPIO_DIR0
,
184 * mv88e6352_g2_scratch_gpio_get_pctl - get pin control setting
185 * @chip: chip private data
187 * @func: function number
189 * Note that the function numbers themselves may vary by chipset.
191 static int mv88e6352_g2_scratch_gpio_get_pctl(struct mv88e6xxx_chip
*chip
,
192 unsigned int pin
, int *func
)
194 int reg
= MV88E6352_G2_SCRATCH_GPIO_PCTL0
+ (pin
/ 2);
195 int offset
= (pin
& 0x1) ? 4 : 0;
196 u8 mask
= (0x7 << offset
);
200 err
= mv88e6xxx_g2_scratch_read(chip
, reg
, &val
);
204 *func
= (val
& mask
) >> offset
;
210 * mv88e6352_g2_scratch_gpio_set_pctl - set pin control setting
211 * @chip: chip private data
213 * @func: function number
215 static int mv88e6352_g2_scratch_gpio_set_pctl(struct mv88e6xxx_chip
*chip
,
216 unsigned int pin
, int func
)
218 int reg
= MV88E6352_G2_SCRATCH_GPIO_PCTL0
+ (pin
/ 2);
219 int offset
= (pin
& 0x1) ? 4 : 0;
220 u8 mask
= (0x7 << offset
);
224 err
= mv88e6xxx_g2_scratch_read(chip
, reg
, &val
);
228 val
= (val
& ~mask
) | ((func
& mask
) << offset
);
230 return mv88e6xxx_g2_scratch_write(chip
, reg
, val
);
233 const 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
,
243 * mv88e6390_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
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
251 int mv88e6390_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip
*chip
,
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
;
262 err
= mv88e6xxx_g2_scratch_read(chip
, config_data2
, &val
);
266 p0_mode
= val
& MV88E6352_G2_SCRATCH_CONFIG_DATA2_P0_MODE_MASK
;
268 if (p0_mode
== 0x01 || p0_mode
== 0x02)
271 err
= mv88e6xxx_g2_scratch_read(chip
, config_data1
, &val
);
275 no_cpu
= !!(val
& MV88E6352_G2_SCRATCH_CONFIG_DATA1_NO_CPU
);
277 err
= mv88e6xxx_g2_scratch_read(chip
, misc_cfg
, &val
);
281 /* NO_CPU being 0 inverts the meaning of the bit */
283 external
= !external
;
286 val
|= MV88E6352_G2_SCRATCH_MISC_CFG_NORMALSMI
;
288 val
&= ~MV88E6352_G2_SCRATCH_MISC_CFG_NORMALSMI
;
290 return mv88e6xxx_g2_scratch_write(chip
, misc_cfg
, val
);
294 * mv88e6393x_g2_scratch_gpio_set_smi - set gpio muxing for external smi
295 * @chip: chip private data
296 * @external: set mux for external smi, or free for gpio usage
298 * MV88E6191X/6193X/6393X GPIO pins 9 and 10 can be configured as an
299 * external SMI interface or as regular GPIO-s.
301 * They however have a different register layout then the existing
305 int mv88e6393x_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip
*chip
,
308 int misc_cfg
= MV88E6352_G2_SCRATCH_MISC_CFG
;
312 err
= mv88e6xxx_g2_scratch_read(chip
, misc_cfg
, &val
);
317 val
&= ~MV88E6352_G2_SCRATCH_MISC_CFG_NORMALSMI
;
319 val
|= MV88E6352_G2_SCRATCH_MISC_CFG_NORMALSMI
;
321 return mv88e6xxx_g2_scratch_write(chip
, misc_cfg
, val
);
325 * mv88e6352_g2_scratch_port_has_serdes - indicate if a port can have a serdes
326 * @chip: chip private data
327 * @port: port number to check for serdes
329 * Indicates whether the port may have a serdes attached according to the
330 * pin strapping. Returns negative error number, 0 if the port is not
331 * configured to have a serdes, and 1 if the port is configured to have a
334 int mv88e6352_g2_scratch_port_has_serdes(struct mv88e6xxx_chip
*chip
, int port
)
339 err
= mv88e6xxx_g2_scratch_read(chip
, MV88E6352_G2_SCRATCH_CONFIG_DATA3
,
344 if (config3
& MV88E6352_G2_SCRATCH_CONFIG_DATA3_S_SEL
)