⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ibm_emac_rgmii.c

📁 linux-2.6.15.6
💻 C
字号:
/* * drivers/net/ibm_emac/ibm_emac_rgmii.c * * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support. * * Copyright (c) 2004, 2005 Zultys Technologies. * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> * * Based on original work by * 	Matt Porter <mporter@kernel.crashing.org> * 	Copyright 2004 MontaVista Software, Inc. *  * 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/config.h>#include <linux/kernel.h>#include <linux/ethtool.h>#include <asm/io.h>#include "ibm_emac_core.h"#include "ibm_emac_debug.h"/* RGMIIx_FER */#define RGMII_FER_MASK(idx)	(0x7 << ((idx) * 4))#define RGMII_FER_RTBI(idx)	(0x4 << ((idx) * 4))#define RGMII_FER_RGMII(idx)	(0x5 << ((idx) * 4))#define RGMII_FER_TBI(idx)	(0x6 << ((idx) * 4))#define RGMII_FER_GMII(idx)	(0x7 << ((idx) * 4))/* RGMIIx_SSR */#define RGMII_SSR_MASK(idx)	(0x7 << ((idx) * 8))#define RGMII_SSR_100(idx)	(0x2 << ((idx) * 8))#define RGMII_SSR_1000(idx)	(0x4 << ((idx) * 8))/* RGMII bridge supports only GMII/TBI and RGMII/RTBI PHYs */static inline int rgmii_valid_mode(int phy_mode){	return  phy_mode == PHY_MODE_GMII ||		phy_mode == PHY_MODE_RGMII ||		phy_mode == PHY_MODE_TBI ||		phy_mode == PHY_MODE_RTBI;}static inline const char *rgmii_mode_name(int mode){	switch (mode) {	case PHY_MODE_RGMII:		return "RGMII";	case PHY_MODE_TBI:		return "TBI";	case PHY_MODE_GMII:		return "GMII";	case PHY_MODE_RTBI:		return "RTBI";	default:		BUG();	}}static inline u32 rgmii_mode_mask(int mode, int input){	switch (mode) {	case PHY_MODE_RGMII:		return RGMII_FER_RGMII(input);	case PHY_MODE_TBI:		return RGMII_FER_TBI(input);	case PHY_MODE_GMII:		return RGMII_FER_GMII(input);	case PHY_MODE_RTBI:		return RGMII_FER_RTBI(input);	default:		BUG();	}}static int __init rgmii_init(struct ocp_device *ocpdev, int input, int mode){	struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);	struct rgmii_regs *p;	RGMII_DBG("%d: init(%d, %d)" NL, ocpdev->def->index, input, mode);	if (!dev) {		dev = kzalloc(sizeof(struct ibm_ocp_rgmii), GFP_KERNEL);		if (!dev) {			printk(KERN_ERR			       "rgmii%d: couldn't allocate device structure!\n",			       ocpdev->def->index);			return -ENOMEM;		}		p = (struct rgmii_regs *)ioremap(ocpdev->def->paddr,						 sizeof(struct rgmii_regs));		if (!p) {			printk(KERN_ERR			       "rgmii%d: could not ioremap device registers!\n",			       ocpdev->def->index);			kfree(dev);			return -ENOMEM;		}		dev->base = p;		ocp_set_drvdata(ocpdev, dev);		/* Disable all inputs by default */		out_be32(&p->fer, 0);	} else		p = dev->base;	/* Enable this input */	out_be32(&p->fer, in_be32(&p->fer) | rgmii_mode_mask(mode, input));	printk(KERN_NOTICE "rgmii%d: input %d in %s mode\n",	       ocpdev->def->index, input, rgmii_mode_name(mode));	++dev->users;	return 0;}int __init rgmii_attach(void *emac){	struct ocp_enet_private *dev = emac;	struct ocp_func_emac_data *emacdata = dev->def->additions;	/* Check if we need to attach to a RGMII */	if (emacdata->rgmii_idx >= 0 && rgmii_valid_mode(emacdata->phy_mode)) {		dev->rgmii_input = emacdata->rgmii_mux;		dev->rgmii_dev =		    ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_RGMII,				    emacdata->rgmii_idx);		if (!dev->rgmii_dev) {			printk(KERN_ERR "emac%d: unknown rgmii%d!\n",			       dev->def->index, emacdata->rgmii_idx);			return -ENODEV;		}		if (rgmii_init		    (dev->rgmii_dev, dev->rgmii_input, emacdata->phy_mode)) {			printk(KERN_ERR			       "emac%d: rgmii%d initialization failed!\n",			       dev->def->index, emacdata->rgmii_idx);			return -ENODEV;		}	}	return 0;}void rgmii_set_speed(struct ocp_device *ocpdev, int input, int speed){	struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);	u32 ssr = in_be32(&dev->base->ssr) & ~RGMII_SSR_MASK(input);	RGMII_DBG("%d: speed(%d, %d)" NL, ocpdev->def->index, input, speed);	if (speed == SPEED_1000)		ssr |= RGMII_SSR_1000(input);	else if (speed == SPEED_100)		ssr |= RGMII_SSR_100(input);	out_be32(&dev->base->ssr, ssr);}void __exit __rgmii_fini(struct ocp_device *ocpdev, int input){	struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);	BUG_ON(!dev || dev->users == 0);	RGMII_DBG("%d: fini(%d)" NL, ocpdev->def->index, input);	/* Disable this input */	out_be32(&dev->base->fer,		 in_be32(&dev->base->fer) & ~RGMII_FER_MASK(input));	if (!--dev->users) {		/* Free everything if this is the last user */		ocp_set_drvdata(ocpdev, NULL);		iounmap((void *)dev->base);		kfree(dev);	}}int __rgmii_get_regs_len(struct ocp_device *ocpdev){	return sizeof(struct emac_ethtool_regs_subhdr) +	    sizeof(struct rgmii_regs);}void *rgmii_dump_regs(struct ocp_device *ocpdev, void *buf){	struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);	struct emac_ethtool_regs_subhdr *hdr = buf;	struct rgmii_regs *regs = (struct rgmii_regs *)(hdr + 1);	hdr->version = 0;	hdr->index = ocpdev->def->index;	memcpy_fromio(regs, dev->base, sizeof(struct rgmii_regs));	return regs + 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -