0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/mdio.h>
0011 #include <linux/module.h>
0012
0013 #include "chip.h"
0014 #include "phy.h"
0015
0016 int mv88e6165_phy_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
0017 int addr, int reg, u16 *val)
0018 {
0019 return mv88e6xxx_read(chip, addr, reg, val);
0020 }
0021
0022 int mv88e6165_phy_write(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
0023 int addr, int reg, u16 val)
0024 {
0025 return mv88e6xxx_write(chip, addr, reg, val);
0026 }
0027
0028 int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy, int reg, u16 *val)
0029 {
0030 int addr = phy;
0031 struct mii_bus *bus;
0032
0033 bus = mv88e6xxx_default_mdio_bus(chip);
0034 if (!bus)
0035 return -EOPNOTSUPP;
0036
0037 if (!chip->info->ops->phy_read)
0038 return -EOPNOTSUPP;
0039
0040 return chip->info->ops->phy_read(chip, bus, addr, reg, val);
0041 }
0042
0043 int mv88e6xxx_phy_write(struct mv88e6xxx_chip *chip, int phy, int reg, u16 val)
0044 {
0045 int addr = phy;
0046 struct mii_bus *bus;
0047
0048 bus = mv88e6xxx_default_mdio_bus(chip);
0049 if (!bus)
0050 return -EOPNOTSUPP;
0051
0052 if (!chip->info->ops->phy_write)
0053 return -EOPNOTSUPP;
0054
0055 return chip->info->ops->phy_write(chip, bus, addr, reg, val);
0056 }
0057
0058 static int mv88e6xxx_phy_page_get(struct mv88e6xxx_chip *chip, int phy, u8 page)
0059 {
0060 return mv88e6xxx_phy_write(chip, phy, MV88E6XXX_PHY_PAGE, page);
0061 }
0062
0063 static void mv88e6xxx_phy_page_put(struct mv88e6xxx_chip *chip, int phy)
0064 {
0065 int err;
0066
0067
0068
0069
0070 err = mv88e6xxx_phy_write(chip, phy, MV88E6XXX_PHY_PAGE,
0071 MV88E6XXX_PHY_PAGE_COPPER);
0072 if (unlikely(err)) {
0073 dev_err(chip->dev,
0074 "failed to restore PHY %d page Copper (%d)\n",
0075 phy, err);
0076 }
0077 }
0078
0079 int mv88e6xxx_phy_page_read(struct mv88e6xxx_chip *chip, int phy,
0080 u8 page, int reg, u16 *val)
0081 {
0082 int err;
0083
0084
0085 if (reg == MV88E6XXX_PHY_PAGE)
0086 return -EINVAL;
0087
0088 err = mv88e6xxx_phy_page_get(chip, phy, page);
0089 if (!err) {
0090 err = mv88e6xxx_phy_read(chip, phy, reg, val);
0091 mv88e6xxx_phy_page_put(chip, phy);
0092 }
0093
0094 return err;
0095 }
0096
0097 int mv88e6xxx_phy_page_write(struct mv88e6xxx_chip *chip, int phy,
0098 u8 page, int reg, u16 val)
0099 {
0100 int err;
0101
0102
0103 if (reg == MV88E6XXX_PHY_PAGE)
0104 return -EINVAL;
0105
0106 err = mv88e6xxx_phy_page_get(chip, phy, page);
0107 if (!err) {
0108 err = mv88e6xxx_phy_write(chip, phy, MV88E6XXX_PHY_PAGE, page);
0109 if (!err)
0110 err = mv88e6xxx_phy_write(chip, phy, reg, val);
0111
0112 mv88e6xxx_phy_page_put(chip, phy);
0113 }
0114
0115 return err;
0116 }
0117
0118 static int mv88e6xxx_phy_ppu_disable(struct mv88e6xxx_chip *chip)
0119 {
0120 if (!chip->info->ops->ppu_disable)
0121 return 0;
0122
0123 return chip->info->ops->ppu_disable(chip);
0124 }
0125
0126 static int mv88e6xxx_phy_ppu_enable(struct mv88e6xxx_chip *chip)
0127 {
0128 if (!chip->info->ops->ppu_enable)
0129 return 0;
0130
0131 return chip->info->ops->ppu_enable(chip);
0132 }
0133
0134 static void mv88e6xxx_phy_ppu_reenable_work(struct work_struct *ugly)
0135 {
0136 struct mv88e6xxx_chip *chip;
0137
0138 chip = container_of(ugly, struct mv88e6xxx_chip, ppu_work);
0139
0140 mv88e6xxx_reg_lock(chip);
0141
0142 if (mutex_trylock(&chip->ppu_mutex)) {
0143 if (mv88e6xxx_phy_ppu_enable(chip) == 0)
0144 chip->ppu_disabled = 0;
0145 mutex_unlock(&chip->ppu_mutex);
0146 }
0147
0148 mv88e6xxx_reg_unlock(chip);
0149 }
0150
0151 static void mv88e6xxx_phy_ppu_reenable_timer(struct timer_list *t)
0152 {
0153 struct mv88e6xxx_chip *chip = from_timer(chip, t, ppu_timer);
0154
0155 schedule_work(&chip->ppu_work);
0156 }
0157
0158 static int mv88e6xxx_phy_ppu_access_get(struct mv88e6xxx_chip *chip)
0159 {
0160 int ret;
0161
0162 mutex_lock(&chip->ppu_mutex);
0163
0164
0165
0166
0167
0168
0169 if (!chip->ppu_disabled) {
0170 ret = mv88e6xxx_phy_ppu_disable(chip);
0171 if (ret < 0) {
0172 mutex_unlock(&chip->ppu_mutex);
0173 return ret;
0174 }
0175 chip->ppu_disabled = 1;
0176 } else {
0177 del_timer(&chip->ppu_timer);
0178 ret = 0;
0179 }
0180
0181 return ret;
0182 }
0183
0184 static void mv88e6xxx_phy_ppu_access_put(struct mv88e6xxx_chip *chip)
0185 {
0186
0187 mod_timer(&chip->ppu_timer, jiffies + msecs_to_jiffies(10));
0188 mutex_unlock(&chip->ppu_mutex);
0189 }
0190
0191 static void mv88e6xxx_phy_ppu_state_init(struct mv88e6xxx_chip *chip)
0192 {
0193 mutex_init(&chip->ppu_mutex);
0194 INIT_WORK(&chip->ppu_work, mv88e6xxx_phy_ppu_reenable_work);
0195 timer_setup(&chip->ppu_timer, mv88e6xxx_phy_ppu_reenable_timer, 0);
0196 }
0197
0198 static void mv88e6xxx_phy_ppu_state_destroy(struct mv88e6xxx_chip *chip)
0199 {
0200 del_timer_sync(&chip->ppu_timer);
0201 }
0202
0203 int mv88e6185_phy_ppu_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
0204 int addr, int reg, u16 *val)
0205 {
0206 int err;
0207
0208 err = mv88e6xxx_phy_ppu_access_get(chip);
0209 if (!err) {
0210 err = mv88e6xxx_read(chip, addr, reg, val);
0211 mv88e6xxx_phy_ppu_access_put(chip);
0212 }
0213
0214 return err;
0215 }
0216
0217 int mv88e6185_phy_ppu_write(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
0218 int addr, int reg, u16 val)
0219 {
0220 int err;
0221
0222 err = mv88e6xxx_phy_ppu_access_get(chip);
0223 if (!err) {
0224 err = mv88e6xxx_write(chip, addr, reg, val);
0225 mv88e6xxx_phy_ppu_access_put(chip);
0226 }
0227
0228 return err;
0229 }
0230
0231 void mv88e6xxx_phy_init(struct mv88e6xxx_chip *chip)
0232 {
0233 if (chip->info->ops->ppu_enable && chip->info->ops->ppu_disable)
0234 mv88e6xxx_phy_ppu_state_init(chip);
0235 }
0236
0237 void mv88e6xxx_phy_destroy(struct mv88e6xxx_chip *chip)
0238 {
0239 if (chip->info->ops->ppu_enable && chip->info->ops->ppu_disable)
0240 mv88e6xxx_phy_ppu_state_destroy(chip);
0241 }
0242
0243 int mv88e6xxx_phy_setup(struct mv88e6xxx_chip *chip)
0244 {
0245 return mv88e6xxx_phy_ppu_enable(chip);
0246 }