[PATCH 6/9] qe_lib: Add QE SoC support

Kumar Gala galak at kernel.crashing.org
Sat Sep 30 00:12:59 EST 2006


On Sep 29, 2006, at 5:35 AM, Li Yang wrote:

> Signed-off-by: Li Yang <leoli at freescale.com>
> Signed-off-by: Kim Phillips <kim.phillips at freescale.com>
>
> ---
>  arch/powerpc/sysdev/qe_lib/qe.c |  176 ++++++++++++++++++++++++++++ 
> +++++++++++
>  include/linux/fsl_devices.h     |   39 ++++++++-
>  2 files changed, 214 insertions(+), 1 deletions(-)

As I've stated in the past make this use of_device instead of  
platform_device.

- k

>
> diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/ 
> qe_lib/qe.c
> new file mode 100644
> index 0000000..df3e826
> --- /dev/null
> +++ b/arch/powerpc/sysdev/qe_lib/qe.c
> @@ -0,0 +1,176 @@
> +/*
> + * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights  
> reserved.
> + *
> + * Author: Li Yang <LeoLi at freescale.com>
> + *
> + * Description:
> + * FSL QE SOC setup.
> + *
> + * 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/stddef.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/errno.h>
> +#include <linux/major.h>
> +#include <linux/delay.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <linux/fsl_devices.h>
> +
> +#include <asm/system.h>
> +#include <asm/atomic.h>
> +#include <asm/io.h>
> +#include <asm/irq.h>
> +#include <asm/prom.h>
> +#include <sysdev/fsl_soc.h>
> +#include <mm/mmu_decl.h>
> +
> +static phys_addr_t qebase = -1;
> +
> +phys_addr_t get_qe_base(void)
> +{
> +	struct device_node *qe;
> +
> +	if (qebase != -1)
> +		return qebase;
> +
> +	qe = of_find_node_by_type(NULL, "qe");
> +	if (qe) {
> +		unsigned int size;
> +		void *prop = get_property(qe, "reg", &size);
> +		qebase = of_translate_address(qe, prop);
> +		of_node_put(qe);
> +	};
> +
> +	return qebase;
> +}
> +
> +EXPORT_SYMBOL(get_qe_base);
> +
> +static int __init ucc_geth_of_init(void)
> +{
> +	struct device_node *np;
> +	unsigned int i, ucc_num;
> +	struct platform_device *ugeth_dev;
> +	struct resource res;
> +	int ret;
> +
> +	for (np = NULL, i = 0;
> +	     (np = of_find_compatible_node(np, "network", "ucc_geth")) !=  
> NULL;
> +	     i++) {
> +		struct resource r[2];
> +		struct device_node *phy, *mdio;
> +		struct ucc_geth_platform_data ugeth_data;
> +		unsigned int *id;
> +		char *model;
> +		void *mac_addr;
> +		phandle *ph;
> +
> +		memset(r, 0, sizeof(r));
> +		memset(&ugeth_data, 0, sizeof(ugeth_data));
> +
> +		ret = of_address_to_resource(np, 0, &r[0]);
> +		if (ret)
> +			goto err;
> +
> +		ugeth_data.phy_reg_addr = r[0].start;
> +		r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
> +		r[1].flags = IORESOURCE_IRQ;
> +
> +		model = get_property(np, "model", NULL);
> +		ucc_num = *((u32 *) get_property(np, "device-id", NULL));
> +		if ((strstr(model, "UCC") == NULL) ||
> +				(ucc_num < 1) || (ucc_num > 8)) {
> +			ret = -ENODEV;
> +			goto err;
> +		}
> +		
> +		ugeth_dev =
> +		    platform_device_register_simple("ucc_geth", ucc_num - 1,
> +				    &r[0], 2);
> +
> +		if (IS_ERR(ugeth_dev)) {
> +			ret = PTR_ERR(ugeth_dev);
> +			goto err;
> +		}
> +
> +		mac_addr = get_property(np, "mac-address", NULL);
> +		
> +		memcpy(ugeth_data.mac_addr, mac_addr, 6);
> +
> +		ugeth_data.rx_clock = *((u32 *) get_property(np, "rx-clock",
> +					NULL));
> +		ugeth_data.tx_clock = *((u32 *) get_property(np, "tx-clock",
> +					NULL));
> +
> +		ph = (phandle *) get_property(np, "phy-handle", NULL);
> +		phy = of_find_node_by_phandle(*ph);
> +
> +		if (phy == NULL) {
> +			ret = -ENODEV;
> +			goto unreg;
> +		}
> +
> +		mdio = of_get_parent(phy);
> +
> +		id = (u32 *) get_property(phy, "reg", NULL);
> +		ret = of_address_to_resource(mdio, 0, &res);
> +		if (ret) {
> +			of_node_put(phy);
> +			of_node_put(mdio);
> +			goto unreg;
> +		}
> +		
> +		ugeth_data.phy_id = *id;
> +
> +		ugeth_data.phy_interrupt = irq_of_parse_and_map(phy, 0);;
> +		ugeth_data.phy_interface = *((u32 *) get_property(phy,
> +					"interface", NULL));
> +
> +		/* FIXME: Work around for early chip rev.               */
> +		/* There's a bug in initial chip rev(s) in the RGMII ac */
> +		/* timing.						*/
> +		/* The following compensates by writing to the reserved */
> +		/* QE Port Output Hold Registers (CPOH1?).              */	
> +		if ((ugeth_data.phy_interface == ENET_1000_RGMII) ||
> +				(ugeth_data.phy_interface == ENET_100_RGMII) ||
> +				(ugeth_data.phy_interface == ENET_10_RGMII)) {
> +			u32 *tmp_reg = (u32 *) ioremap(get_immrbase()
> +					+ 0x14A8, 0x4);
> +			u32 tmp_val = in_be32(tmp_reg);
> +			if (ucc_num == 1)
> +				out_be32(tmp_reg, tmp_val | 0x00003000);
> +			else if (ucc_num == 2)
> +				out_be32(tmp_reg, tmp_val | 0x0c000000);
> +			iounmap(tmp_reg);
> +		}
> +		
> +		if (ugeth_data.phy_interrupt != 0)
> +			ugeth_data.board_flags |= FSL_UGETH_BRD_HAS_PHY_INTR;
> +
> +		of_node_put(phy);
> +		of_node_put(mdio);
> +
> +		ret = platform_device_add_data(ugeth_dev, &ugeth_data,
> +				sizeof(struct ucc_geth_platform_data));
> +		if (ret)
> +			goto unreg;
> +	}
> +
> +	return 0;
> +
> +unreg:
> +	platform_device_unregister(ugeth_dev);
> +err:
> +	return ret;
> +}
> +
> +arch_initcall(ucc_geth_of_init);
> diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
> index 16fbe59..a16d82f 100644
> --- a/include/linux/fsl_devices.h
> +++ b/include/linux/fsl_devices.h
> @@ -83,7 +83,6 @@ struct fsl_i2c_platform_data {
>  #define FSL_I2C_DEV_SEPARATE_DFSRR	0x00000001
>  #define FSL_I2C_DEV_CLOCK_5200		0x00000002
>
> -
>  enum fsl_usb2_operating_modes {
>  	FSL_USB2_MPH_HOST,
>  	FSL_USB2_DR_HOST,
> @@ -121,5 +120,43 @@ struct fsl_spi_platform_data {
>  	u32	sysclk;
>  };
>
> +/* Ethernet interface (phy management and speed)
> +*/
> +typedef enum enet_interface {
> +	ENET_10_MII,		/* 10 Base T,   MII interface */
> +	ENET_10_RMII,		/* 10 Base T,  RMII interface */
> +	ENET_10_RGMII,		/* 10 Base T, RGMII interface */
> +	ENET_100_MII,		/* 100 Base T,   MII interface */
> +	ENET_100_RMII,		/* 100 Base T,  RMII interface */
> +	ENET_100_RGMII,		/* 100 Base T, RGMII interface */
> +	ENET_1000_GMII,		/* 1000 Base T,  GMII interface */
> +	ENET_1000_RGMII,	/* 1000 Base T, RGMII interface */
> +	ENET_1000_TBI,		/* 1000 Base T,   TBI interface */
> +	ENET_1000_RTBI		/* 1000 Base T,  RTBI interface */
> +} enet_interface_e;
> +
> +struct ucc_geth_platform_data {
> +	/* device specific information */
> +	u32 device_flags;
> +	u32 phy_reg_addr;
> +
> +	/* board specific information */
> +	u32 board_flags;
> +	u8 rx_clock;
> +	u8 tx_clock;
> +	u32 phy_id;
> +	enet_interface_e phy_interface;
> +	u32 phy_interrupt;
> +	u8 mac_addr[6];
> +};
> +
> +/* Flags related to UCC Gigabit Ethernet device features */
> +#define FSL_UGETH_DEV_HAS_GIGABIT		0x00000001
> +#define FSL_UGETH_DEV_HAS_COALESCE		0x00000002
> +#define FSL_UGETH_DEV_HAS_RMON			0x00000004
> +
> +/* Flags in ucc_geth_platform_data */
> +#define FSL_UGETH_BRD_HAS_PHY_INTR		0x00000001	/* if not set use a  
> timer */
> +
>  #endif				/* _FSL_DEVICE_H_ */
>  #endif				/* __KERNEL__ */
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev




More information about the Linuxppc-dev mailing list