blob: c3f55be873b389638ba1d7355bb7b8e317682048 [file] [log] [blame]
Vivien Didelot332aa5c2017-05-01 14:05:12 -04001/*
2 * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support
3 *
4 * Copyright (c) 2008 Marvell Semiconductor
5 * Copyright (c) 2015 CMC Electronics, Inc.
6 * Copyright (c) 2017 Savoir-faire Linux, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include "mv88e6xxx.h"
15#include "global1.h"
16
Vivien Didelot8ee51f62017-05-01 14:05:14 -040017/* Offset 0x02: VTU FID Register */
18
19int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
20 struct mv88e6xxx_vtu_entry *entry)
21{
22 u16 val;
23 int err;
24
25 err = mv88e6xxx_g1_read(chip, GLOBAL_VTU_FID, &val);
26 if (err)
27 return err;
28
29 entry->fid = val & GLOBAL_VTU_FID_MASK;
30
31 return 0;
32}
33
34int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
35 struct mv88e6xxx_vtu_entry *entry)
36{
37 u16 val = entry->fid & GLOBAL_VTU_FID_MASK;
38
39 return mv88e6xxx_g1_write(chip, GLOBAL_VTU_FID, val);
40}
41
Vivien Didelotd2ca1ea2017-05-01 14:05:15 -040042/* Offset 0x03: VTU SID Register */
43
44int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip,
45 struct mv88e6xxx_vtu_entry *entry)
46{
47 u16 val;
48 int err;
49
50 err = mv88e6xxx_g1_read(chip, GLOBAL_VTU_SID, &val);
51 if (err)
52 return err;
53
54 entry->sid = val & GLOBAL_VTU_SID_MASK;
55
56 return 0;
57}
58
59int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip,
60 struct mv88e6xxx_vtu_entry *entry)
61{
62 u16 val = entry->sid & GLOBAL_VTU_SID_MASK;
63
64 return mv88e6xxx_g1_write(chip, GLOBAL_VTU_SID, val);
65}
66
Vivien Didelot332aa5c2017-05-01 14:05:12 -040067/* Offset 0x05: VTU Operation Register */
68
69int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
70{
71 return mv88e6xxx_g1_wait(chip, GLOBAL_VTU_OP, GLOBAL_VTU_OP_BUSY);
72}
73
74int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
75{
76 int err;
77
78 err = mv88e6xxx_g1_write(chip, GLOBAL_VTU_OP, op);
79 if (err)
80 return err;
81
82 return mv88e6xxx_g1_vtu_op_wait(chip);
83}
Vivien Didelotb486d7c2017-05-01 14:05:13 -040084
Vivien Didelot3afb4bd2017-05-01 14:05:16 -040085/* Offset 0x06: VTU VID Register */
86
87int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
88 struct mv88e6xxx_vtu_entry *entry)
89{
90 u16 val;
91 int err;
92
93 err = mv88e6xxx_g1_read(chip, GLOBAL_VTU_VID, &val);
94 if (err)
95 return err;
96
97 entry->vid = val & 0xfff;
98 entry->valid = !!(val & GLOBAL_VTU_VID_VALID);
99
100 return 0;
101}
102
103int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
104 struct mv88e6xxx_vtu_entry *entry)
105{
106 u16 val = entry->vid & 0xfff;
107
108 if (entry->valid)
109 val |= GLOBAL_VTU_VID_VALID;
110
111 return mv88e6xxx_g1_write(chip, GLOBAL_VTU_VID, val);
112}
113
Vivien Didelotb486d7c2017-05-01 14:05:13 -0400114/* VLAN Translation Unit Operations */
115
Vivien Didelotf169e5e2017-05-01 14:05:17 -0400116int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
117 struct mv88e6xxx_vtu_entry *entry)
118{
119 int err;
120
121 err = mv88e6xxx_g1_vtu_op_wait(chip);
122 if (err)
123 return err;
124
125 /* To get the next higher active VID, the VTU GetNext operation can be
126 * started again without setting the VID registers since it already
127 * contains the last VID.
128 *
129 * To save a few hardware accesses and abstract this to the caller,
130 * write the VID only once, when the entry is given as invalid.
131 */
132 if (!entry->valid) {
133 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
134 if (err)
135 return err;
136 }
137
138 err = mv88e6xxx_g1_vtu_op(chip, GLOBAL_VTU_OP_VTU_GET_NEXT);
139 if (err)
140 return err;
141
142 return mv88e6xxx_g1_vtu_vid_read(chip, entry);
143}
144
Vivien Didelotb486d7c2017-05-01 14:05:13 -0400145int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
146{
147 int err;
148
149 err = mv88e6xxx_g1_vtu_op_wait(chip);
150 if (err)
151 return err;
152
153 return mv88e6xxx_g1_vtu_op(chip, GLOBAL_VTU_OP_FLUSH_ALL);
154}