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

📄 fsl_soc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * FSL SoC setup code * * Maintained by Kumar Gala (see MAINTAINERS for contact information) * * 2006 (c) MontaVista Software, Inc. * Vitaly Bordug <vbordug@ru.mvista.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/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/of_platform.h>#include <linux/phy.h>#include <linux/spi/spi.h>#include <linux/fsl_devices.h>#include <linux/fs_enet_pd.h>#include <linux/fs_uart_pd.h>#include <asm/system.h>#include <asm/atomic.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/time.h>#include <asm/prom.h>#include <sysdev/fsl_soc.h>#include <mm/mmu_decl.h>#include <asm/cpm2.h>extern void init_fcc_ioports(struct fs_platform_info*);extern void init_fec_ioports(struct fs_platform_info*);extern void init_smc_ioports(struct fs_uart_platform_info*);static phys_addr_t immrbase = -1;phys_addr_t get_immrbase(void){	struct device_node *soc;	if (immrbase != -1)		return immrbase;	soc = of_find_node_by_type(NULL, "soc");	if (soc) {		int size;		const void *prop = of_get_property(soc, "reg", &size);		if (prop)			immrbase = of_translate_address(soc, prop);		of_node_put(soc);	}	return immrbase;}EXPORT_SYMBOL(get_immrbase);#if defined(CONFIG_CPM2) || defined(CONFIG_8xx)static u32 brgfreq = -1;u32 get_brgfreq(void){	struct device_node *node;	const unsigned int *prop;	int size;	if (brgfreq != -1)		return brgfreq;	node = of_find_compatible_node(NULL, NULL, "fsl,cpm-brg");	if (node) {		prop = of_get_property(node, "clock-frequency", &size);		if (prop && size == 4)			brgfreq = *prop;		of_node_put(node);		return brgfreq;	}	/* Legacy device binding -- will go away when no users are left. */	node = of_find_node_by_type(NULL, "cpm");	if (node) {		prop = of_get_property(node, "brg-frequency", &size);		if (prop && size == 4)			brgfreq = *prop;		of_node_put(node);	}	return brgfreq;}EXPORT_SYMBOL(get_brgfreq);static u32 fs_baudrate = -1;u32 get_baudrate(void){	struct device_node *node;	if (fs_baudrate != -1)		return fs_baudrate;	node = of_find_node_by_type(NULL, "serial");	if (node) {		int size;		const unsigned int *prop = of_get_property(node,				"current-speed", &size);		if (prop)			fs_baudrate = *prop;		of_node_put(node);	}	return fs_baudrate;}EXPORT_SYMBOL(get_baudrate);#endif /* CONFIG_CPM2 */static int __init gfar_mdio_of_init(void){	struct device_node *np;	unsigned int i;	struct platform_device *mdio_dev;	struct resource res;	int ret;	for (np = NULL, i = 0;	     (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL;	     i++) {		int k;		struct device_node *child = NULL;		struct gianfar_mdio_data mdio_data;		memset(&res, 0, sizeof(res));		memset(&mdio_data, 0, sizeof(mdio_data));		ret = of_address_to_resource(np, 0, &res);		if (ret)			goto err;		mdio_dev =		    platform_device_register_simple("fsl-gianfar_mdio",						    res.start, &res, 1);		if (IS_ERR(mdio_dev)) {			ret = PTR_ERR(mdio_dev);			goto err;		}		for (k = 0; k < 32; k++)			mdio_data.irq[k] = PHY_POLL;		while ((child = of_get_next_child(np, child)) != NULL) {			int irq = irq_of_parse_and_map(child, 0);			if (irq != NO_IRQ) {				const u32 *id = of_get_property(child,							"reg", NULL);				mdio_data.irq[*id] = irq;			}		}		ret =		    platform_device_add_data(mdio_dev, &mdio_data,					     sizeof(struct gianfar_mdio_data));		if (ret)			goto unreg;	}	return 0;unreg:	platform_device_unregister(mdio_dev);err:	return ret;}arch_initcall(gfar_mdio_of_init);static const char *gfar_tx_intr = "tx";static const char *gfar_rx_intr = "rx";static const char *gfar_err_intr = "error";static int __init gfar_of_init(void){	struct device_node *np;	unsigned int i;	struct platform_device *gfar_dev;	struct resource res;	int ret;	for (np = NULL, i = 0;	     (np = of_find_compatible_node(np, "network", "gianfar")) != NULL;	     i++) {		struct resource r[4];		struct device_node *phy, *mdio;		struct gianfar_platform_data gfar_data;		const unsigned int *id;		const char *model;		const char *ctype;		const void *mac_addr;		const phandle *ph;		int n_res = 2;		memset(r, 0, sizeof(r));		memset(&gfar_data, 0, sizeof(gfar_data));		ret = of_address_to_resource(np, 0, &r[0]);		if (ret)			goto err;		of_irq_to_resource(np, 0, &r[1]);		model = of_get_property(np, "model", NULL);		/* If we aren't the FEC we have multiple interrupts */		if (model && strcasecmp(model, "FEC")) {			r[1].name = gfar_tx_intr;			r[2].name = gfar_rx_intr;			of_irq_to_resource(np, 1, &r[2]);			r[3].name = gfar_err_intr;			of_irq_to_resource(np, 2, &r[3]);			n_res += 2;		}		gfar_dev =		    platform_device_register_simple("fsl-gianfar", i, &r[0],						    n_res);		if (IS_ERR(gfar_dev)) {			ret = PTR_ERR(gfar_dev);			goto err;		}		mac_addr = of_get_mac_address(np);		if (mac_addr)			memcpy(gfar_data.mac_addr, mac_addr, 6);		if (model && !strcasecmp(model, "TSEC"))			gfar_data.device_flags =			    FSL_GIANFAR_DEV_HAS_GIGABIT |			    FSL_GIANFAR_DEV_HAS_COALESCE |			    FSL_GIANFAR_DEV_HAS_RMON |			    FSL_GIANFAR_DEV_HAS_MULTI_INTR;		if (model && !strcasecmp(model, "eTSEC"))			gfar_data.device_flags =			    FSL_GIANFAR_DEV_HAS_GIGABIT |			    FSL_GIANFAR_DEV_HAS_COALESCE |			    FSL_GIANFAR_DEV_HAS_RMON |			    FSL_GIANFAR_DEV_HAS_MULTI_INTR |			    FSL_GIANFAR_DEV_HAS_CSUM |			    FSL_GIANFAR_DEV_HAS_VLAN |			    FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;		ctype = of_get_property(np, "phy-connection-type", NULL);		/* We only care about rgmii-id.  The rest are autodetected */		if (ctype && !strcmp(ctype, "rgmii-id"))			gfar_data.interface = PHY_INTERFACE_MODE_RGMII_ID;		else			gfar_data.interface = PHY_INTERFACE_MODE_MII;		ph = of_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 = of_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;		}		gfar_data.phy_id = *id;		gfar_data.bus_id = res.start;		of_node_put(phy);		of_node_put(mdio);		ret =		    platform_device_add_data(gfar_dev, &gfar_data,					     sizeof(struct						    gianfar_platform_data));		if (ret)			goto unreg;	}	return 0;unreg:	platform_device_unregister(gfar_dev);err:	return ret;}arch_initcall(gfar_of_init);#ifdef CONFIG_I2C_BOARDINFO#include <linux/i2c.h>struct i2c_driver_device {	char	*of_device;	char	*i2c_driver;	char	*i2c_type;};static struct i2c_driver_device i2c_devices[] __initdata = {	{"ricoh,rs5c372a", "rtc-rs5c372", "rs5c372a",},	{"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",},	{"ricoh,rv5c386",  "rtc-rs5c372", "rv5c386",},	{"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",},	{"dallas,ds1307",  "rtc-ds1307",  "ds1307",},	{"dallas,ds1337",  "rtc-ds1307",  "ds1337",},	{"dallas,ds1338",  "rtc-ds1307",  "ds1338",},	{"dallas,ds1339",  "rtc-ds1307",  "ds1339",},	{"dallas,ds1340",  "rtc-ds1307",  "ds1340",},	{"stm,m41t00",     "rtc-ds1307",  "m41t00"},	{"dallas,ds1374",  "rtc-ds1374",  "rtc-ds1374",},};static int __init of_find_i2c_driver(struct device_node *node,				     struct i2c_board_info *info){	int i;	for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {		if (!of_device_is_compatible(node, i2c_devices[i].of_device))			continue;		if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver,			    KOBJ_NAME_LEN) >= KOBJ_NAME_LEN ||		    strlcpy(info->type, i2c_devices[i].i2c_type,			    I2C_NAME_SIZE) >= I2C_NAME_SIZE)			return -ENOMEM;		return 0;	}	return -ENODEV;}static void __init of_register_i2c_devices(struct device_node *adap_node,					   int bus_num){	struct device_node *node = NULL;	while ((node = of_get_next_child(adap_node, node))) {		struct i2c_board_info info = {};		const u32 *addr;		int len;		addr = of_get_property(node, "reg", &len);		if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {			printk(KERN_WARNING "fsl_soc.c: invalid i2c device entry\n");			continue;		}		info.irq = irq_of_parse_and_map(node, 0);		if (info.irq == NO_IRQ)			info.irq = -1;		if (of_find_i2c_driver(node, &info) < 0)			continue;		info.addr = *addr;		i2c_register_board_info(bus_num, &info, 1);	}}static int __init fsl_i2c_of_init(void){	struct device_node *np;	unsigned int i;	struct platform_device *i2c_dev;	int ret;	for (np = NULL, i = 0;	     (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;	     i++) {		struct resource r[2];		struct fsl_i2c_platform_data i2c_data;		const unsigned char *flags = NULL;		memset(&r, 0, sizeof(r));		memset(&i2c_data, 0, sizeof(i2c_data));		ret = of_address_to_resource(np, 0, &r[0]);		if (ret)			goto err;		of_irq_to_resource(np, 0, &r[1]);		i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);		if (IS_ERR(i2c_dev)) {			ret = PTR_ERR(i2c_dev);			goto err;		}		i2c_data.device_flags = 0;		flags = of_get_property(np, "dfsrr", NULL);		if (flags)			i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR;		flags = of_get_property(np, "fsl5200-clocking", NULL);		if (flags)			i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200;		ret =		    platform_device_add_data(i2c_dev, &i2c_data,					     sizeof(struct						    fsl_i2c_platform_data));		if (ret)			goto unreg;		of_register_i2c_devices(np, i);	}	return 0;unreg:	platform_device_unregister(i2c_dev);err:	return ret;}arch_initcall(fsl_i2c_of_init);#endif

⌨️ 快捷键说明

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