diff options
author | Arnd Bergmann <arnd@arndb.de> | 2012-11-12 22:54:08 +0100 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2012-11-12 22:54:08 +0100 |
commit | 8a6ff8a0a2bc51b29681aab093b349c9eb32acf5 (patch) | |
tree | 7ee7315a4aa9b33cba73cf46e59187157a00866a /drivers/net/phy/at803x.c | |
parent | 65829ef5a0b9bdffa34b35479853d24e547cfde8 (diff) | |
parent | 75984df05d86956541795f01e62d7dc67bc522fd (diff) | |
download | op-kernel-dev-8a6ff8a0a2bc51b29681aab093b349c9eb32acf5.zip op-kernel-dev-8a6ff8a0a2bc51b29681aab093b349c9eb32acf5.tar.gz |
Merge tag 'for-3.8-at91_header_clean' of git://github.com/at91linux/linux-at91 into next/headers
From Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>:
arm: at91: mach header cleanup
This first patch serie start the cleanup of the header in mach
by moving all the platform data to include/linux/platform_data
and move the board header and drivers header next to them
* tag 'for-3.8-at91_header_clean' of git://github.com/at91linux/linux-at91:
arm: at91: move at91rm9200 rtc header in drivers/rtc
arm: at91: move reset controller header to arm/arm/mach-at91
arm: at91: move pit define to the driver
arm: at91: move at91_shdwc.h to arch/arm/mach-at91
arm: at91: move board header to arch/arm/mach-at91
arn: at91: move at91_tc.h to arch/arm/mach-at91
arm: at91 move at91_aic.h to arch/arm/mach-at91
arm: at91 move board.h to arch/arm/mach-at91
arm: at91: move platfarm_data to include/linux/platform_data/atmel.h
arm: at91: drop machine defconfig
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/net/phy/at803x.c')
-rw-r--r-- | drivers/net/phy/at803x.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c new file mode 100644 index 0000000..45cbc10 --- /dev/null +++ b/drivers/net/phy/at803x.c @@ -0,0 +1,176 @@ +/* + * drivers/net/phy/at803x.c + * + * Driver for Atheros 803x PHY + * + * Author: Matus Ujhelyi <ujhelyi.m@gmail.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/phy.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> + +#define AT803X_INTR_ENABLE 0x12 +#define AT803X_INTR_STATUS 0x13 +#define AT803X_WOL_ENABLE 0x01 +#define AT803X_DEVICE_ADDR 0x03 +#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C +#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B +#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A +#define AT803X_MMD_ACCESS_CONTROL 0x0D +#define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E +#define AT803X_FUNC_DATA 0x4003 + +MODULE_DESCRIPTION("Atheros 803x PHY driver"); +MODULE_AUTHOR("Matus Ujhelyi"); +MODULE_LICENSE("GPL"); + +static void at803x_set_wol_mac_addr(struct phy_device *phydev) +{ + struct net_device *ndev = phydev->attached_dev; + const u8 *mac; + unsigned int i, offsets[] = { + AT803X_LOC_MAC_ADDR_32_47_OFFSET, + AT803X_LOC_MAC_ADDR_16_31_OFFSET, + AT803X_LOC_MAC_ADDR_0_15_OFFSET, + }; + + if (!ndev) + return; + + mac = (const u8 *) ndev->dev_addr; + + if (!is_valid_ether_addr(mac)) + return; + + for (i = 0; i < 3; i++) { + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, + AT803X_DEVICE_ADDR); + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, + offsets[i]); + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, + AT803X_FUNC_DATA); + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, + mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); + } +} + +static int at803x_config_init(struct phy_device *phydev) +{ + int val; + u32 features; + int status; + + features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI | + SUPPORTED_FIBRE | SUPPORTED_BNC; + + val = phy_read(phydev, MII_BMSR); + if (val < 0) + return val; + + if (val & BMSR_ANEGCAPABLE) + features |= SUPPORTED_Autoneg; + if (val & BMSR_100FULL) + features |= SUPPORTED_100baseT_Full; + if (val & BMSR_100HALF) + features |= SUPPORTED_100baseT_Half; + if (val & BMSR_10FULL) + features |= SUPPORTED_10baseT_Full; + if (val & BMSR_10HALF) + features |= SUPPORTED_10baseT_Half; + + if (val & BMSR_ESTATEN) { + val = phy_read(phydev, MII_ESTATUS); + if (val < 0) + return val; + + if (val & ESTATUS_1000_TFULL) + features |= SUPPORTED_1000baseT_Full; + if (val & ESTATUS_1000_THALF) + features |= SUPPORTED_1000baseT_Half; + } + + phydev->supported = features; + phydev->advertising = features; + + /* enable WOL */ + at803x_set_wol_mac_addr(phydev); + status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE); + status = phy_read(phydev, AT803X_INTR_STATUS); + + return 0; +} + +/* ATHEROS 8035 */ +static struct phy_driver at8035_driver = { + .phy_id = 0x004dd072, + .name = "Atheros 8035 ethernet", + .phy_id_mask = 0xffffffef, + .config_init = at803x_config_init, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .driver = { + .owner = THIS_MODULE, + }, +}; + +/* ATHEROS 8030 */ +static struct phy_driver at8030_driver = { + .phy_id = 0x004dd076, + .name = "Atheros 8030 ethernet", + .phy_id_mask = 0xffffffef, + .config_init = at803x_config_init, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .driver = { + .owner = THIS_MODULE, + }, +}; + +static int __init atheros_init(void) +{ + int ret; + + ret = phy_driver_register(&at8035_driver); + if (ret) + goto err1; + + ret = phy_driver_register(&at8030_driver); + if (ret) + goto err2; + + return 0; + +err2: + phy_driver_unregister(&at8035_driver); +err1: + return ret; +} + +static void __exit atheros_exit(void) +{ + phy_driver_unregister(&at8035_driver); + phy_driver_unregister(&at8030_driver); +} + +module_init(atheros_init); +module_exit(atheros_exit); + +static struct mdio_device_id __maybe_unused atheros_tbl[] = { + { 0x004dd076, 0xffffffef }, + { 0x004dd072, 0xffffffef }, + { } +}; + +MODULE_DEVICE_TABLE(mdio, atheros_tbl); |