0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "chip.h"
0012 #include "global2.h"
0013
0014
0015 static int mv88e6xxx_g2_scratch_read(struct mv88e6xxx_chip *chip, int reg,
0016 u8 *data)
0017 {
0018 u16 value;
0019 int err;
0020
0021 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC,
0022 reg << 8);
0023 if (err)
0024 return err;
0025
0026 err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC, &value);
0027 if (err)
0028 return err;
0029
0030 *data = (value & MV88E6XXX_G2_SCRATCH_MISC_DATA_MASK);
0031
0032 return 0;
0033 }
0034
0035 static int mv88e6xxx_g2_scratch_write(struct mv88e6xxx_chip *chip, int reg,
0036 u8 data)
0037 {
0038 u16 value = (reg << 8) | data;
0039
0040 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC,
0041 MV88E6XXX_G2_SCRATCH_MISC_UPDATE | value);
0042 }
0043
0044
0045
0046
0047
0048
0049
0050
0051 static int mv88e6xxx_g2_scratch_get_bit(struct mv88e6xxx_chip *chip,
0052 int base_reg, unsigned int offset,
0053 int *set)
0054 {
0055 int reg = base_reg + (offset / 8);
0056 u8 mask = (1 << (offset & 0x7));
0057 u8 val;
0058 int err;
0059
0060 err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
0061 if (err)
0062 return err;
0063
0064 *set = !!(mask & val);
0065
0066 return 0;
0067 }
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 static int mv88e6xxx_g2_scratch_set_bit(struct mv88e6xxx_chip *chip,
0079 int base_reg, unsigned int offset,
0080 int set)
0081 {
0082 int reg = base_reg + (offset / 8);
0083 u8 mask = (1 << (offset & 0x7));
0084 u8 val;
0085 int err;
0086
0087 err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
0088 if (err)
0089 return err;
0090
0091 if (set)
0092 val |= mask;
0093 else
0094 val &= ~mask;
0095
0096 return mv88e6xxx_g2_scratch_write(chip, reg, val);
0097 }
0098
0099
0100
0101
0102
0103
0104
0105
0106 static int mv88e6352_g2_scratch_gpio_get_data(struct mv88e6xxx_chip *chip,
0107 unsigned int pin)
0108 {
0109 int val = 0;
0110 int err;
0111
0112 err = mv88e6xxx_g2_scratch_get_bit(chip,
0113 MV88E6352_G2_SCRATCH_GPIO_DATA0,
0114 pin, &val);
0115 if (err)
0116 return err;
0117
0118 return val;
0119 }
0120
0121
0122
0123
0124
0125
0126
0127 static int mv88e6352_g2_scratch_gpio_set_data(struct mv88e6xxx_chip *chip,
0128 unsigned int pin, int value)
0129 {
0130 u8 mask = (1 << (pin & 0x7));
0131 int offset = (pin / 8);
0132 int reg;
0133
0134 reg = MV88E6352_G2_SCRATCH_GPIO_DATA0 + offset;
0135
0136 if (value)
0137 chip->gpio_data[offset] |= mask;
0138 else
0139 chip->gpio_data[offset] &= ~mask;
0140
0141 return mv88e6xxx_g2_scratch_write(chip, reg, chip->gpio_data[offset]);
0142 }
0143
0144
0145
0146
0147
0148
0149
0150
0151 static int mv88e6352_g2_scratch_gpio_get_dir(struct mv88e6xxx_chip *chip,
0152 unsigned int pin)
0153 {
0154 int val = 0;
0155 int err;
0156
0157 err = mv88e6xxx_g2_scratch_get_bit(chip,
0158 MV88E6352_G2_SCRATCH_GPIO_DIR0,
0159 pin, &val);
0160 if (err)
0161 return err;
0162
0163 return val;
0164 }
0165
0166
0167
0168
0169
0170
0171
0172 static int mv88e6352_g2_scratch_gpio_set_dir(struct mv88e6xxx_chip *chip,
0173 unsigned int pin, bool input)
0174 {
0175 int value = (input ? MV88E6352_G2_SCRATCH_GPIO_DIR_IN :
0176 MV88E6352_G2_SCRATCH_GPIO_DIR_OUT);
0177
0178 return mv88e6xxx_g2_scratch_set_bit(chip,
0179 MV88E6352_G2_SCRATCH_GPIO_DIR0,
0180 pin, value);
0181 }
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 static int mv88e6352_g2_scratch_gpio_get_pctl(struct mv88e6xxx_chip *chip,
0192 unsigned int pin, int *func)
0193 {
0194 int reg = MV88E6352_G2_SCRATCH_GPIO_PCTL0 + (pin / 2);
0195 int offset = (pin & 0x1) ? 4 : 0;
0196 u8 mask = (0x7 << offset);
0197 int err;
0198 u8 val;
0199
0200 err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
0201 if (err)
0202 return err;
0203
0204 *func = (val & mask) >> offset;
0205
0206 return 0;
0207 }
0208
0209
0210
0211
0212
0213
0214
0215 static int mv88e6352_g2_scratch_gpio_set_pctl(struct mv88e6xxx_chip *chip,
0216 unsigned int pin, int func)
0217 {
0218 int reg = MV88E6352_G2_SCRATCH_GPIO_PCTL0 + (pin / 2);
0219 int offset = (pin & 0x1) ? 4 : 0;
0220 u8 mask = (0x7 << offset);
0221 int err;
0222 u8 val;
0223
0224 err = mv88e6xxx_g2_scratch_read(chip, reg, &val);
0225 if (err)
0226 return err;
0227
0228 val = (val & ~mask) | ((func & mask) << offset);
0229
0230 return mv88e6xxx_g2_scratch_write(chip, reg, val);
0231 }
0232
0233 const struct mv88e6xxx_gpio_ops mv88e6352_gpio_ops = {
0234 .get_data = mv88e6352_g2_scratch_gpio_get_data,
0235 .set_data = mv88e6352_g2_scratch_gpio_set_data,
0236 .get_dir = mv88e6352_g2_scratch_gpio_get_dir,
0237 .set_dir = mv88e6352_g2_scratch_gpio_set_dir,
0238 .get_pctl = mv88e6352_g2_scratch_gpio_get_pctl,
0239 .set_pctl = mv88e6352_g2_scratch_gpio_set_pctl,
0240 };
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 int mv88e6xxx_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip *chip,
0252 bool external)
0253 {
0254 int misc_cfg = MV88E6352_G2_SCRATCH_MISC_CFG;
0255 int config_data1 = MV88E6352_G2_SCRATCH_CONFIG_DATA1;
0256 int config_data2 = MV88E6352_G2_SCRATCH_CONFIG_DATA2;
0257 bool no_cpu;
0258 u8 p0_mode;
0259 int err;
0260 u8 val;
0261
0262 err = mv88e6xxx_g2_scratch_read(chip, config_data2, &val);
0263 if (err)
0264 return err;
0265
0266 p0_mode = val & MV88E6352_G2_SCRATCH_CONFIG_DATA2_P0_MODE_MASK;
0267
0268 if (p0_mode == 0x01 || p0_mode == 0x02)
0269 return -EBUSY;
0270
0271 err = mv88e6xxx_g2_scratch_read(chip, config_data1, &val);
0272 if (err)
0273 return err;
0274
0275 no_cpu = !!(val & MV88E6352_G2_SCRATCH_CONFIG_DATA1_NO_CPU);
0276
0277 err = mv88e6xxx_g2_scratch_read(chip, misc_cfg, &val);
0278 if (err)
0279 return err;
0280
0281
0282 if (!no_cpu)
0283 external = !external;
0284
0285 if (external)
0286 val |= MV88E6352_G2_SCRATCH_MISC_CFG_NORMALSMI;
0287 else
0288 val &= ~MV88E6352_G2_SCRATCH_MISC_CFG_NORMALSMI;
0289
0290 return mv88e6xxx_g2_scratch_write(chip, misc_cfg, val);
0291 }
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303 int mv88e6352_g2_scratch_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
0304 {
0305 u8 config3, p;
0306 int err;
0307
0308 err = mv88e6xxx_g2_scratch_read(chip, MV88E6352_G2_SCRATCH_CONFIG_DATA3,
0309 &config3);
0310 if (err)
0311 return err;
0312
0313 if (config3 & MV88E6352_G2_SCRATCH_CONFIG_DATA3_S_SEL)
0314 p = 5;
0315 else
0316 p = 4;
0317
0318 return port == p;
0319 }