xref: /openbmc/linux/drivers/net/dsa/mv88e6xxx/global2_scratch.c (revision 93707cbabcc8baf2b2b5f4a99c1f08ee83eb7abd)
1 /*
2  * Marvell 88E6xxx Switch Global 2 Scratch & Misc Registers support
3  *
4  * Copyright (c) 2008 Marvell Semiconductor
5  *
6  * Copyright (c) 2017 National Instruments
7  *      Brandon Streiff <brandon.streiff@ni.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  */
14 
15 #include "chip.h"
16 #include "global2.h"
17 
18 /* Offset 0x1A: Scratch and Misc. Register */
19 static int mv88e6xxx_g2_scratch_read(struct mv88e6xxx_chip *chip, int reg,
20 				     u8 *data)
21 {
22 	u16 value;
23 	int err;
24 
25 	err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC,
26 				 reg << 8);
27 	if (err)
28 		return err;
29 
30 	err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC, &value);
31 	if (err)
32 		return err;
33 
34 	*data = (value & MV88E6XXX_G2_SCRATCH_MISC_DATA_MASK);
35 
36 	return 0;
37 }
38 
39 static int mv88e6xxx_g2_scratch_write(struct mv88e6xxx_chip *chip, int reg,
40 				      u8 data)
41 {
42 	u16 value = (reg << 8) | data;
43 
44 	return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC, value);
45 }
46 
47 /**
48  * mv88e6xxx_g2_scratch_gpio_get_bit - get a bit
49  * @chip: chip private data
50  * @nr: bit index
51  * @set: is bit set?
52  */
53 static int mv88e6xxx_g2_scratch_get_bit(struct mv88e6xxx_chip *chip,
54 					int base_reg, unsigned int offset,
55 					int *set)
56 {
57 	int reg = base_reg + (offset / 8);
58 	u8 mask = (1 << (offset & 0x7));
59 	u8 val;
60 	int err;
61 
62 	err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
63 	if (err)
64 		return err;
65 
66 	*set = !!(mask & val);
67 
68 	return 0;
69 }
70 
71 /**
72  * mv88e6xxx_g2_scratch_gpio_set_bit - set (or clear) a bit
73  * @chip: chip private data
74  * @nr: bit index
75  * @set: set if true, clear if false
76  *
77  * Helper function for dealing with the direction and data registers.
78  */
79 static int mv88e6xxx_g2_scratch_set_bit(struct mv88e6xxx_chip *chip,
80 					int base_reg, unsigned int offset,
81 					int set)
82 {
83 	int reg = base_reg + (offset / 8);
84 	u8 mask = (1 << (offset & 0x7));
85 	u8 val;
86 	int err;
87 
88 	err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
89 	if (err)
90 		return err;
91 
92 	if (set)
93 		val |= mask;
94 	else
95 		val &= ~mask;
96 
97 	return mv88e6xxx_g2_scratch_write(chip, reg, val);
98 }
99 
100 /**
101  * mv88e6352_g2_scratch_gpio_get_data - get data on gpio pin
102  * @chip: chip private data
103  * @pin: gpio index
104  *
105  * Return: 0 for low, 1 for high, negative error
106  */
107 static int mv88e6352_g2_scratch_gpio_get_data(struct mv88e6xxx_chip *chip,
108 					      unsigned int pin)
109 {
110 	int val = 0;
111 	int err;
112 
113 	err = mv88e6xxx_g2_scratch_get_bit(chip,
114 					   MV88E6352_G2_SCRATCH_GPIO_DATA0,
115 					   pin, &val);
116 	if (err)
117 		return err;
118 
119 	return val;
120 }
121 
122 /**
123  * mv88e6352_g2_scratch_gpio_set_data - set data on gpio pin
124  * @chip: chip private data
125  * @pin: gpio index
126  * @value: value to set
127  */
128 static int mv88e6352_g2_scratch_gpio_set_data(struct mv88e6xxx_chip *chip,
129 					      unsigned int pin, int value)
130 {
131 	u8 mask = (1 << (pin & 0x7));
132 	int offset = (pin / 8);
133 	int reg;
134 
135 	reg = MV88E6352_G2_SCRATCH_GPIO_DATA0 + offset;
136 
137 	if (value)
138 		chip->gpio_data[offset] |= mask;
139 	else
140 		chip->gpio_data[offset] &= ~mask;
141 
142 	return mv88e6xxx_g2_scratch_write(chip, reg, chip->gpio_data[offset]);
143 }
144 
145 /**
146  * mv88e6352_g2_scratch_gpio_get_dir - get direction of gpio pin
147  * @chip: chip private data
148  * @pin: gpio index
149  *
150  * Return: 0 for output, 1 for input (same as GPIOF_DIR_XXX).
151  */
152 static int mv88e6352_g2_scratch_gpio_get_dir(struct mv88e6xxx_chip *chip,
153 					     unsigned int pin)
154 {
155 	int val = 0;
156 	int err;
157 
158 	err = mv88e6xxx_g2_scratch_get_bit(chip,
159 					   MV88E6352_G2_SCRATCH_GPIO_DIR0,
160 					   pin, &val);
161 	if (err)
162 		return err;
163 
164 	return val;
165 }
166 
167 /**
168  * mv88e6352_g2_scratch_gpio_set_dir - set direction of gpio pin
169  * @chip: chip private data
170  * @pin: gpio index
171  */
172 static 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  */
191 static 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  */
215 static 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 
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,
240 };
241