#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
#include <linux/phy.h>
+#include <linux/phy_fixed.h>
+#include <linux/spi/spi.h>
#include <linux/fsl_devices.h>
#include <linux/fs_enet_pd.h>
#include <linux/fs_uart_pd.h>
soc = of_find_node_by_type(NULL, "soc");
if (soc) {
- unsigned int size;
- const void *prop = of_get_property(soc, "reg", &size);
+ int size;
+ u32 naddr;
+ const u32 *prop = of_get_property(soc, "#address-cells", &size);
+ if (prop && size == 4)
+ naddr = *prop;
+ else
+ naddr = 2;
+
+ prop = of_get_property(soc, "ranges", &size);
if (prop)
- immrbase = of_translate_address(soc, prop);
+ immrbase = of_translate_address(soc, prop + naddr);
+
of_node_put(soc);
- };
+ }
return immrbase;
}
u32 get_brgfreq(void)
{
struct device_node *node;
+ const unsigned int *prop;
+ int size;
if (brgfreq != -1)
return brgfreq;
- node = of_find_node_by_type(NULL, "cpm");
+ node = of_find_compatible_node(NULL, NULL, "fsl,cpm-brg");
if (node) {
- unsigned int size;
- const unsigned int *prop = of_get_property(node,
- "brg-frequency", &size);
+ prop = of_get_property(node, "clock-frequency", &size);
+ if (prop && size == 4)
+ brgfreq = *prop;
- if (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;
}
node = of_find_node_by_type(NULL, "serial");
if (node) {
- unsigned int size;
+ 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)
+#ifdef CONFIG_FIXED_PHY
+static int __init of_add_fixed_phys(void)
{
+ int ret;
struct device_node *np;
- unsigned int i;
+ u32 *fixed_link;
+ struct fixed_phy_status status = {};
+
+ for_each_node_by_name(np, "ethernet") {
+ fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL);
+ if (!fixed_link)
+ continue;
+
+ status.link = 1;
+ status.duplex = fixed_link[1];
+ status.speed = fixed_link[2];
+ status.pause = fixed_link[3];
+ status.asym_pause = fixed_link[4];
+
+ ret = fixed_phy_add(PHY_POLL, fixed_link[0], &status);
+ if (ret) {
+ of_node_put(np);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+arch_initcall(of_add_fixed_phys);
+#endif /* CONFIG_FIXED_PHY */
+
+static int __init gfar_mdio_of_init(void)
+{
+ struct device_node *np = NULL;
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++) {
+ np = of_find_compatible_node(np, NULL, "fsl,gianfar-mdio");
+
+ /* try the deprecated version */
+ if (!np)
+ np = of_find_compatible_node(np, "mdio", "gianfar");
+
+ if (np) {
int k;
struct device_node *child = NULL;
struct gianfar_mdio_data mdio_data;
goto unreg;
}
+ of_node_put(np);
return 0;
unreg:
platform_device_unregister(mdio_dev);
err:
+ of_node_put(np);
return ret;
}
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;
gfar_data.interface = PHY_INTERFACE_MODE_MII;
ph = of_get_property(np, "phy-handle", NULL);
- phy = of_find_node_by_phandle(*ph);
+ if (ph == NULL) {
+ u32 *fixed_link;
- if (phy == NULL) {
- ret = -ENODEV;
- goto unreg;
- }
+ fixed_link = (u32 *)of_get_property(np, "fixed-link",
+ NULL);
+ if (!fixed_link) {
+ ret = -ENODEV;
+ goto unreg;
+ }
- mdio = of_get_parent(phy);
+ gfar_data.bus_id = 0;
+ gfar_data.phy_id = fixed_link[0];
+ } else {
+ 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;
- 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
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;
+ unsigned int i = 0;
struct platform_device *i2c_dev;
int ret;
- for (np = NULL, i = 0;
- (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;
- i++) {
+ for_each_compatible_node(np, NULL, "fsl-i2c") {
struct resource r[2];
struct fsl_i2c_platform_data i2c_data;
const unsigned char *flags = NULL;
fsl_i2c_platform_data));
if (ret)
goto unreg;
+
+ of_register_i2c_devices(np, i++);
}
return 0;
}
arch_initcall(fsl_i2c_of_init);
+#endif
#ifdef CONFIG_PPC_83xx
static int __init mpc83xx_wdt_init(void)
static int __init fsl_usb_of_init(void)
{
struct device_node *np;
- unsigned int i;
+ unsigned int i = 0;
struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL,
*usb_dev_dr_client = NULL;
int ret;
- for (np = NULL, i = 0;
- (np = of_find_compatible_node(np, "usb", "fsl-usb2-mph")) != NULL;
- i++) {
+ for_each_compatible_node(np, NULL, "fsl-usb2-mph") {
struct resource r[2];
struct fsl_usb2_platform_data usb_data;
const unsigned char *prop = NULL;
fsl_usb2_platform_data));
if (ret)
goto unreg_mph;
+ i++;
}
- for (np = NULL;
- (np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL;
- i++) {
+ for_each_compatible_node(np, NULL, "fsl-usb2-dr") {
struct resource r[2];
struct fsl_usb2_platform_data usb_data;
const unsigned char *prop = NULL;
fsl_usb2_platform_data))))
goto unreg_dr;
}
+ i++;
}
return 0;
arch_initcall(fsl_usb_of_init);
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
#ifdef CONFIG_CPM2
extern void init_scc_ioports(struct fs_uart_platform_info*);
static int __init fsl_pcmcia_of_init(void)
{
- struct device_node *np = NULL;
+ struct device_node *np;
/*
* Register all the devices which type is "pcmcia"
*/
- while ((np = of_find_compatible_node(np,
- "pcmcia", "fsl,pq-pcmcia")) != NULL)
- of_platform_device_create(np, "m8xx-pcmcia", NULL);
+ for_each_compatible_node(np, "pcmcia", "fsl,pq-pcmcia")
+ of_platform_device_create(np, "m8xx-pcmcia", NULL);
return 0;
}
arch_initcall(cpm_smc_uart_of_init);
#endif /* CONFIG_8xx */
+#endif /* CONFIG_PPC_CPM_NEW_BINDING */
+
+int __init fsl_spi_init(struct spi_board_info *board_infos,
+ unsigned int num_board_infos,
+ void (*activate_cs)(u8 cs, u8 polarity),
+ void (*deactivate_cs)(u8 cs, u8 polarity))
+{
+ struct device_node *np;
+ unsigned int i;
+ const u32 *sysclk;
+
+ /* SPI controller is either clocked from QE or SoC clock */
+ np = of_find_compatible_node(NULL, NULL, "fsl,qe");
+ if (!np)
+ np = of_find_node_by_type(NULL, "qe");
+
+ if (!np)
+ np = of_find_node_by_type(NULL, "soc");
+
+ if (!np)
+ return -ENODEV;
+
+ sysclk = of_get_property(np, "bus-frequency", NULL);
+ if (!sysclk)
+ return -ENODEV;
+
+ for (np = NULL, i = 1;
+ (np = of_find_compatible_node(np, "spi", "fsl_spi")) != NULL;
+ i++) {
+ int ret = 0;
+ unsigned int j;
+ const void *prop;
+ struct resource res[2];
+ struct platform_device *pdev;
+ struct fsl_spi_platform_data pdata = {
+ .activate_cs = activate_cs,
+ .deactivate_cs = deactivate_cs,
+ };
+
+ memset(res, 0, sizeof(res));
+
+ pdata.sysclk = *sysclk;
+
+ prop = of_get_property(np, "reg", NULL);
+ if (!prop)
+ goto err;
+ pdata.bus_num = *(u32 *)prop;
+
+ prop = of_get_property(np, "mode", NULL);
+ if (prop && !strcmp(prop, "cpu-qe"))
+ pdata.qe_mode = 1;
+
+ for (j = 0; j < num_board_infos; j++) {
+ if (board_infos[j].bus_num == pdata.bus_num)
+ pdata.max_chipselect++;
+ }
+
+ if (!pdata.max_chipselect)
+ goto err;
+
+ ret = of_address_to_resource(np, 0, &res[0]);
+ if (ret)
+ goto err;
+
+ ret = of_irq_to_resource(np, 0, &res[1]);
+ if (ret == NO_IRQ)
+ goto err;
+
+ pdev = platform_device_alloc("mpc83xx_spi", i);
+ if (!pdev)
+ goto err;
+
+ ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+ if (ret)
+ goto unreg;
+
+ ret = platform_device_add_resources(pdev, res,
+ ARRAY_SIZE(res));
+ if (ret)
+ goto unreg;
+
+ ret = platform_device_register(pdev);
+ if (ret)
+ goto unreg;
+
+ continue;
+unreg:
+ platform_device_del(pdev);
+err:
+ continue;
+ }
+
+ return spi_register_board_info(board_infos, num_board_infos);
+}
+
+#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx)
+static __be32 __iomem *rstcr;
+
+static int __init setup_rstcr(void)
+{
+ struct device_node *np;
+ np = of_find_node_by_name(NULL, "global-utilities");
+ if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
+ const u32 *prop = of_get_property(np, "reg", NULL);
+ if (prop) {
+ /* map reset control register
+ * 0xE00B0 is offset of reset control register
+ */
+ rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff);
+ if (!rstcr)
+ printk (KERN_EMERG "Error: reset control "
+ "register not mapped!\n");
+ }
+ } else
+ printk (KERN_INFO "rstcr compatible register does not exist!\n");
+ if (np)
+ of_node_put(np);
+ return 0;
+}
+
+arch_initcall(setup_rstcr);
+
+void fsl_rstcr_restart(char *cmd)
+{
+ local_irq_disable();
+ if (rstcr)
+ /* set reset control register */
+ out_be32(rstcr, 0x2); /* HRESET_REQ */
+
+ while (1) ;
+}
+#endif