123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- /*
- * ADM6996 switch driver
- *
- * Copyright (c) 2008 Felix Fietkau <[email protected]>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License v2 as published by the
- * Free Software Foundation
- */
- #include <linux/kernel.h>
- #include <linux/string.h>
- #include <linux/errno.h>
- #include <linux/unistd.h>
- #include <linux/slab.h>
- #include <linux/interrupt.h>
- #include <linux/init.h>
- #include <linux/delay.h>
- #include <linux/netdevice.h>
- #include <linux/etherdevice.h>
- #include <linux/skbuff.h>
- #include <linux/spinlock.h>
- #include <linux/mm.h>
- #include <linux/module.h>
- #include <linux/mii.h>
- #include <linux/ethtool.h>
- #include <linux/phy.h>
- #include <asm/io.h>
- #include <asm/irq.h>
- #include <asm/uaccess.h>
- #include "adm6996.h"
- MODULE_DESCRIPTION("Infineon ADM6996 Switch");
- MODULE_AUTHOR("Felix Fietkau");
- MODULE_LICENSE("GPL");
- struct adm6996_priv {
- /* use abstraction for regops, we want to add gpio support in the future */
- u16 (*read)(struct phy_device *phydev, enum admreg reg);
- void (*write)(struct phy_device *phydev, enum admreg reg, u16 val);
- };
- #define to_adm(_phy) ((struct adm6996_priv *) (_phy)->priv)
- static inline u16
- r16(struct phy_device *pdev, enum admreg reg)
- {
- return to_adm(pdev)->read(pdev, reg);
- }
- static inline void
- w16(struct phy_device *pdev, enum admreg reg, u16 val)
- {
- to_adm(pdev)->write(pdev, reg, val);
- }
- static u16
- adm6996_read_mii_reg(struct phy_device *phydev, enum admreg reg)
- {
- return phydev->bus->read(phydev->bus, PHYADDR(reg));
- }
- static void
- adm6996_write_mii_reg(struct phy_device *phydev, enum admreg reg, u16 val)
- {
- phydev->bus->write(phydev->bus, PHYADDR(reg), val);
- }
- static int adm6996_config_init(struct phy_device *pdev)
- {
- int i;
- printk("%s: ADM6996 PHY driver attached.\n", pdev->attached_dev->name);
- pdev->supported = ADVERTISED_100baseT_Full;
- pdev->advertising = ADVERTISED_100baseT_Full;
- /* initialize port and vlan settings */
- for (i = 0; i < ADM_PHY_PORTS; i++) {
- w16(pdev, adm_portcfg[i], ADM_PORTCFG_INIT |
- ADM_PORTCFG_PVID((i == ADM_WAN_PORT) ? 1 : 0));
- }
- w16(pdev, adm_portcfg[5], ADM_PORTCFG_CPU);
- /* reset all ports */
- for (i = 0; i < ADM_PHY_PORTS; i++) {
- w16(pdev, ADM_PHY_PORT(i), ADM_PHYCFG_INIT);
- }
- return 0;
- }
- static int adm6996_read_status(struct phy_device *phydev)
- {
- phydev->speed = SPEED_100;
- phydev->duplex = DUPLEX_FULL;
- phydev->state = PHY_UP;
- return 0;
- }
- static int adm6996_config_aneg(struct phy_device *phydev)
- {
- return 0;
- }
- static int adm6996_probe(struct phy_device *pdev)
- {
- struct adm6996_priv *priv;
- priv = kzalloc(sizeof(struct adm6996_priv), GFP_KERNEL);
- if (priv == NULL)
- return -ENOMEM;
- priv->read = adm6996_read_mii_reg;
- priv->write = adm6996_write_mii_reg;
- pdev->priv = priv;
- return 0;
- }
- static void adm6996_remove(struct phy_device *pdev)
- {
- kfree(pdev->priv);
- }
- static bool adm6996_detect(struct mii_bus *bus, int addr)
- {
- u16 reg;
- /* we only attach to phy id 0 */
- if (addr != 0)
- return false;
- /* look for the switch on the bus */
- reg = bus->read(bus, PHYADDR(ADM_SIG0)) & ADM_SIG0_MASK;
- if (reg != ADM_SIG0_VAL)
- return false;
- reg = bus->read(bus, PHYADDR(ADM_SIG1)) & ADM_SIG1_MASK;
- if (reg != ADM_SIG1_VAL)
- return false;
- return true;
- }
- static struct phy_driver adm6996_driver = {
- .name = "Infineon ADM6996",
- .features = PHY_BASIC_FEATURES,
- .detect = adm6996_detect,
- .probe = adm6996_probe,
- .remove = adm6996_remove,
- .config_init = &adm6996_config_init,
- .config_aneg = &adm6996_config_aneg,
- .read_status = &adm6996_read_status,
- .driver = { .owner = THIS_MODULE,},
- };
- static int __init adm6996_init(void)
- {
- return phy_driver_register(&adm6996_driver);
- }
- static void __exit adm6996_exit(void)
- {
- phy_driver_unregister(&adm6996_driver);
- }
- module_init(adm6996_init);
- module_exit(adm6996_exit);
|