1/* 2 * ar80xx.c: ar80xx(ar8031/ar8033/ar8035) PHY driver 3 * 4 * Copyright (c) 2013 The Linux Foundation. All rights reserved. 5 * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> 6 * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 2 11 * of the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 */ 18 19#include <linux/if.h> 20#include <linux/module.h> 21#include <linux/init.h> 22#include <linux/list.h> 23#include <linux/if_ether.h> 24#include <linux/skbuff.h> 25#include <linux/netdevice.h> 26#include <linux/netlink.h> 27#include <linux/bitops.h> 28#include <net/genetlink.h> 29#include <linux/delay.h> 30#include <linux/phy.h> 31#include <linux/netdevice.h> 32#include <linux/etherdevice.h> 33#include <linux/lockdep.h> 34#include "ar80xx.h" 35#include <asm/mach-ath79/ar71xx_regs.h> 36 37static int 38ar8033_config_init(struct phy_device *pdev) 39{ 40 u32 v; 41 v = phy_read(pdev, AR80XX_REG_CHIP_CONFIG); 42 phy_write(pdev, AR80XX_REG_CHIP_CONFIG, AR80XX_BT_BX_REG_SEL | v); 43 44 pdev->autoneg = AUTONEG_ENABLE; 45 46 return 0; 47} 48 49static int 50ar8033_read_status(struct phy_device *pdev) 51{ 52 void __iomem *base; 53 54 genphy_read_status(pdev); 55 56 base = ioremap(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); 57 58 if (pdev->speed == SPEED_1000) { 59 __raw_writel( ETH_SGMII_GIGE_SET(1) | ETH_SGMII_CLK_SEL_SET(1), 60 base + ETH_SGMII_ADDRESS_OFFSET); 61 } else if (pdev->speed == SPEED_100) { 62 __raw_writel( ETH_SGMII_PHASE0_COUNT_SET(1) | ETH_SGMII_PHASE1_COUNT_SET(1), 63 base + ETH_SGMII_ADDRESS_OFFSET); 64 } else { 65 __raw_writel( ETH_SGMII_PHASE0_COUNT_SET(19) | ETH_SGMII_PHASE1_COUNT_SET(19), 66 base + ETH_SGMII_ADDRESS_OFFSET); 67 } 68 iounmap(base); 69 70 return 0; 71} 72 73static int 74ar8033_config_aneg(struct phy_device *pdev) 75{ 76 u32 v; 77 78 v = phy_read(pdev, MII_BMCR); 79 phy_write(pdev, MII_BMCR, v | AR80XX_AUTO_NEGO); 80 81 v = genphy_config_aneg(pdev); 82 if (v < 0) { 83 printk("%s, Error: 0x%x\n", __func__, v); 84 return v; 85 } 86 87 return 0; 88} 89 90static int 91ar8033_probe(struct phy_device *pdev) 92{ 93 return 0; 94} 95 96static void 97ar8033_remove(struct phy_device *pdev) 98{ 99} 100 101static struct phy_driver ar80xx_phy_drivers[] = { 102 { 103 .phy_id = AR80XX_PHY_ID_AR8033, 104 .name = "Qualcomm Atheros AR8033 PHY", 105 .phy_id_mask = AR80XX_PHY_ID_MASK, 106 .features = PHY_GBIT_FEATURES, 107 .probe = ar8033_probe, 108 .remove = ar8033_remove, 109 .config_init = &ar8033_config_init, 110 .config_aneg = &ar8033_config_aneg, 111 .read_status = &ar8033_read_status, 112 .driver = { .owner = THIS_MODULE }, 113 }, 114}; 115 116int __init 117ar80xx_phy_init(void) 118{ 119 int ret; 120 int i; 121 122 for (i = 0; i < ARRAY_SIZE(ar80xx_phy_drivers); i++) { 123 ret = phy_driver_register(&ar80xx_phy_drivers[i]); 124 if (ret) { 125 while (i-- > 0) 126 phy_driver_unregister(&ar80xx_phy_drivers[i]); 127 return ret; 128 } 129 } 130 return 0; 131} 132 133void __exit 134ar80xx_phy_exit(void) 135{ 136 int i; 137 138 for (i = 0; i < ARRAY_SIZE(ar80xx_phy_drivers); i++) 139 phy_driver_unregister(&ar80xx_phy_drivers[i]); 140} 141 142module_init(ar80xx_phy_init); 143module_exit(ar80xx_phy_exit); 144MODULE_LICENSE("GPL"); 145 146