aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/fsl_soc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/fsl_soc.c')
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c187
1 files changed, 170 insertions, 17 deletions
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 1cf29c9d4408..3ace7474809e 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -24,6 +24,7 @@
#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>
@@ -52,13 +53,13 @@ phys_addr_t get_immrbase(void)
soc = of_find_node_by_type(NULL, "soc");
if (soc) {
- unsigned int size;
+ 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;
}
@@ -72,20 +73,31 @@ 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_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;
}
@@ -103,14 +115,14 @@ u32 get_baudrate(void)
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;
}
@@ -319,34 +331,46 @@ static struct i2c_driver_device i2c_devices[] __initdata = {
{"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)
+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;
- strncpy(info->driver_name, i2c_devices[i].i2c_driver, KOBJ_NAME_LEN);
- strncpy(info->type, i2c_devices[i].i2c_type, I2C_NAME_SIZE);
+ 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)
+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;
+ 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_ioc.c: invalid i2c device entry\n");
+ printk(KERN_WARNING "fsl_soc.c: invalid i2c device entry\n");
continue;
}
@@ -357,7 +381,6 @@ static void __init of_register_i2c_devices(struct device_node *adap_node, int bu
if (of_find_i2c_driver(node, &info) < 0)
continue;
- info.platform_data = NULL;
info.addr = *addr;
i2c_register_board_info(bus_num, &info, 1);
@@ -648,6 +671,7 @@ err:
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*);
@@ -1187,3 +1211,132 @@ err:
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_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