diff options
author | Vivien Didelot <vivien.didelot@savoirfairelinux.com> | 2016-07-18 20:45:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-19 22:42:00 -0400 |
commit | f22ab64123da18b96bf8b3d0801c802c73797a9f (patch) | |
tree | e45f7d05563efb2bdf534986c65fe59c3a524b7a /drivers/net/dsa | |
parent | 9729934c4ff6893456e9a885718b75856e1a42ae (diff) |
net: dsa: mv88e6xxx: extract device mapping
The Device Mapping register is an indirect table access.
Provide helpers to access this table and explicit the checking of the
new DSA_RTABLE_NONE routing table value.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 75 |
1 files changed, 60 insertions, 15 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 1e39fa604d46..9b2525a5d958 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c | |||
@@ -216,6 +216,32 @@ static int mv88e6xxx_write(struct mv88e6xxx_chip *chip, | |||
216 | return 0; | 216 | return 0; |
217 | } | 217 | } |
218 | 218 | ||
219 | /* Indirect write to single pointer-data register with an Update bit */ | ||
220 | static int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, | ||
221 | u16 update) | ||
222 | { | ||
223 | u16 val; | ||
224 | int i, err; | ||
225 | |||
226 | /* Wait until the previous operation is completed */ | ||
227 | for (i = 0; i < 16; ++i) { | ||
228 | err = mv88e6xxx_read(chip, addr, reg, &val); | ||
229 | if (err) | ||
230 | return err; | ||
231 | |||
232 | if (!(val & BIT(15))) | ||
233 | break; | ||
234 | } | ||
235 | |||
236 | if (i == 16) | ||
237 | return -ETIMEDOUT; | ||
238 | |||
239 | /* Set the Update bit to trigger a write operation */ | ||
240 | val = BIT(15) | update; | ||
241 | |||
242 | return mv88e6xxx_write(chip, addr, reg, val); | ||
243 | } | ||
244 | |||
219 | static int _mv88e6xxx_reg_read(struct mv88e6xxx_chip *chip, int addr, int reg) | 245 | static int _mv88e6xxx_reg_read(struct mv88e6xxx_chip *chip, int addr, int reg) |
220 | { | 246 | { |
221 | u16 val; | 247 | u16 val; |
@@ -3094,9 +3120,39 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip) | |||
3094 | return 0; | 3120 | return 0; |
3095 | } | 3121 | } |
3096 | 3122 | ||
3123 | static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, | ||
3124 | int target, int port) | ||
3125 | { | ||
3126 | u16 val = (target << 8) | (port & 0xf); | ||
3127 | |||
3128 | return mv88e6xxx_update(chip, REG_GLOBAL2, GLOBAL2_DEVICE_MAPPING, val); | ||
3129 | } | ||
3130 | |||
3131 | static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip) | ||
3132 | { | ||
3133 | int target, port; | ||
3134 | int err; | ||
3135 | |||
3136 | /* Initialize the routing port to the 32 possible target devices */ | ||
3137 | for (target = 0; target < 32; ++target) { | ||
3138 | port = 0xf; | ||
3139 | |||
3140 | if (target < DSA_MAX_SWITCHES) { | ||
3141 | port = chip->ds->rtable[target]; | ||
3142 | if (port == DSA_RTABLE_NONE) | ||
3143 | port = 0xf; | ||
3144 | } | ||
3145 | |||
3146 | err = mv88e6xxx_g2_device_mapping_write(chip, target, port); | ||
3147 | if (err) | ||
3148 | break; | ||
3149 | } | ||
3150 | |||
3151 | return err; | ||
3152 | } | ||
3153 | |||
3097 | static int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) | 3154 | static int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) |
3098 | { | 3155 | { |
3099 | struct dsa_switch *ds = chip->ds; | ||
3100 | int err; | 3156 | int err; |
3101 | int i; | 3157 | int i; |
3102 | 3158 | ||
@@ -3120,20 +3176,9 @@ static int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) | |||
3120 | return err; | 3176 | return err; |
3121 | 3177 | ||
3122 | /* Program the DSA routing table. */ | 3178 | /* Program the DSA routing table. */ |
3123 | for (i = 0; i < 32; i++) { | 3179 | err = mv88e6xxx_g2_set_device_mapping(chip); |
3124 | int nexthop = 0x1f; | 3180 | if (err) |
3125 | 3181 | return err; | |
3126 | if (i != ds->index && i < DSA_MAX_SWITCHES) | ||
3127 | nexthop = ds->rtable[i] & 0x1f; | ||
3128 | |||
3129 | err = _mv88e6xxx_reg_write( | ||
3130 | chip, REG_GLOBAL2, | ||
3131 | GLOBAL2_DEVICE_MAPPING, | ||
3132 | GLOBAL2_DEVICE_MAPPING_UPDATE | | ||
3133 | (i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) | nexthop); | ||
3134 | if (err) | ||
3135 | return err; | ||
3136 | } | ||
3137 | 3182 | ||
3138 | /* Clear all trunk masks. */ | 3183 | /* Clear all trunk masks. */ |
3139 | for (i = 0; i < 8; i++) { | 3184 | for (i = 0; i < 8; i++) { |