diff options
Diffstat (limited to 'arch/powerpc/sysdev/fsl_soc.c')
-rw-r--r-- | arch/powerpc/sysdev/fsl_soc.c | 187 |
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 @@ | |||
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/of_platform.h> | 25 | #include <linux/of_platform.h> |
26 | #include <linux/phy.h> | 26 | #include <linux/phy.h> |
27 | #include <linux/spi/spi.h> | ||
27 | #include <linux/fsl_devices.h> | 28 | #include <linux/fsl_devices.h> |
28 | #include <linux/fs_enet_pd.h> | 29 | #include <linux/fs_enet_pd.h> |
29 | #include <linux/fs_uart_pd.h> | 30 | #include <linux/fs_uart_pd.h> |
@@ -52,13 +53,13 @@ phys_addr_t get_immrbase(void) | |||
52 | 53 | ||
53 | soc = of_find_node_by_type(NULL, "soc"); | 54 | soc = of_find_node_by_type(NULL, "soc"); |
54 | if (soc) { | 55 | if (soc) { |
55 | unsigned int size; | 56 | int size; |
56 | const void *prop = of_get_property(soc, "reg", &size); | 57 | const void *prop = of_get_property(soc, "reg", &size); |
57 | 58 | ||
58 | if (prop) | 59 | if (prop) |
59 | immrbase = of_translate_address(soc, prop); | 60 | immrbase = of_translate_address(soc, prop); |
60 | of_node_put(soc); | 61 | of_node_put(soc); |
61 | }; | 62 | } |
62 | 63 | ||
63 | return immrbase; | 64 | return immrbase; |
64 | } | 65 | } |
@@ -72,20 +73,31 @@ static u32 brgfreq = -1; | |||
72 | u32 get_brgfreq(void) | 73 | u32 get_brgfreq(void) |
73 | { | 74 | { |
74 | struct device_node *node; | 75 | struct device_node *node; |
76 | const unsigned int *prop; | ||
77 | int size; | ||
75 | 78 | ||
76 | if (brgfreq != -1) | 79 | if (brgfreq != -1) |
77 | return brgfreq; | 80 | return brgfreq; |
78 | 81 | ||
79 | node = of_find_node_by_type(NULL, "cpm"); | 82 | node = of_find_compatible_node(NULL, NULL, "fsl,cpm-brg"); |
80 | if (node) { | 83 | if (node) { |
81 | unsigned int size; | 84 | prop = of_get_property(node, "clock-frequency", &size); |
82 | const unsigned int *prop = of_get_property(node, | 85 | if (prop && size == 4) |
83 | "brg-frequency", &size); | 86 | brgfreq = *prop; |
84 | 87 | ||
85 | if (prop) | 88 | of_node_put(node); |
89 | return brgfreq; | ||
90 | } | ||
91 | |||
92 | /* Legacy device binding -- will go away when no users are left. */ | ||
93 | node = of_find_node_by_type(NULL, "cpm"); | ||
94 | if (node) { | ||
95 | prop = of_get_property(node, "brg-frequency", &size); | ||
96 | if (prop && size == 4) | ||
86 | brgfreq = *prop; | 97 | brgfreq = *prop; |
98 | |||
87 | of_node_put(node); | 99 | of_node_put(node); |
88 | }; | 100 | } |
89 | 101 | ||
90 | return brgfreq; | 102 | return brgfreq; |
91 | } | 103 | } |
@@ -103,14 +115,14 @@ u32 get_baudrate(void) | |||
103 | 115 | ||
104 | node = of_find_node_by_type(NULL, "serial"); | 116 | node = of_find_node_by_type(NULL, "serial"); |
105 | if (node) { | 117 | if (node) { |
106 | unsigned int size; | 118 | int size; |
107 | const unsigned int *prop = of_get_property(node, | 119 | const unsigned int *prop = of_get_property(node, |
108 | "current-speed", &size); | 120 | "current-speed", &size); |
109 | 121 | ||
110 | if (prop) | 122 | if (prop) |
111 | fs_baudrate = *prop; | 123 | fs_baudrate = *prop; |
112 | of_node_put(node); | 124 | of_node_put(node); |
113 | }; | 125 | } |
114 | 126 | ||
115 | return fs_baudrate; | 127 | return fs_baudrate; |
116 | } | 128 | } |
@@ -319,34 +331,46 @@ static struct i2c_driver_device i2c_devices[] __initdata = { | |||
319 | {"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",}, | 331 | {"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",}, |
320 | {"ricoh,rv5c386", "rtc-rs5c372", "rv5c386",}, | 332 | {"ricoh,rv5c386", "rtc-rs5c372", "rv5c386",}, |
321 | {"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",}, | 333 | {"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",}, |
334 | {"dallas,ds1307", "rtc-ds1307", "ds1307",}, | ||
335 | {"dallas,ds1337", "rtc-ds1307", "ds1337",}, | ||
336 | {"dallas,ds1338", "rtc-ds1307", "ds1338",}, | ||
337 | {"dallas,ds1339", "rtc-ds1307", "ds1339",}, | ||
338 | {"dallas,ds1340", "rtc-ds1307", "ds1340",}, | ||
339 | {"stm,m41t00", "rtc-ds1307", "m41t00"}, | ||
340 | {"dallas,ds1374", "rtc-ds1374", "rtc-ds1374",}, | ||
322 | }; | 341 | }; |
323 | 342 | ||
324 | static int __init of_find_i2c_driver(struct device_node *node, struct i2c_board_info *info) | 343 | static int __init of_find_i2c_driver(struct device_node *node, |
344 | struct i2c_board_info *info) | ||
325 | { | 345 | { |
326 | int i; | 346 | int i; |
327 | 347 | ||
328 | for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) { | 348 | for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) { |
329 | if (!of_device_is_compatible(node, i2c_devices[i].of_device)) | 349 | if (!of_device_is_compatible(node, i2c_devices[i].of_device)) |
330 | continue; | 350 | continue; |
331 | strncpy(info->driver_name, i2c_devices[i].i2c_driver, KOBJ_NAME_LEN); | 351 | if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver, |
332 | strncpy(info->type, i2c_devices[i].i2c_type, I2C_NAME_SIZE); | 352 | KOBJ_NAME_LEN) >= KOBJ_NAME_LEN || |
353 | strlcpy(info->type, i2c_devices[i].i2c_type, | ||
354 | I2C_NAME_SIZE) >= I2C_NAME_SIZE) | ||
355 | return -ENOMEM; | ||
333 | return 0; | 356 | return 0; |
334 | } | 357 | } |
335 | return -ENODEV; | 358 | return -ENODEV; |
336 | } | 359 | } |
337 | 360 | ||
338 | static void __init of_register_i2c_devices(struct device_node *adap_node, int bus_num) | 361 | static void __init of_register_i2c_devices(struct device_node *adap_node, |
362 | int bus_num) | ||
339 | { | 363 | { |
340 | struct device_node *node = NULL; | 364 | struct device_node *node = NULL; |
341 | 365 | ||
342 | while ((node = of_get_next_child(adap_node, node))) { | 366 | while ((node = of_get_next_child(adap_node, node))) { |
343 | struct i2c_board_info info; | 367 | struct i2c_board_info info = {}; |
344 | const u32 *addr; | 368 | const u32 *addr; |
345 | int len; | 369 | int len; |
346 | 370 | ||
347 | addr = of_get_property(node, "reg", &len); | 371 | addr = of_get_property(node, "reg", &len); |
348 | if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) { | 372 | if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) { |
349 | printk(KERN_WARNING "fsl_ioc.c: invalid i2c device entry\n"); | 373 | printk(KERN_WARNING "fsl_soc.c: invalid i2c device entry\n"); |
350 | continue; | 374 | continue; |
351 | } | 375 | } |
352 | 376 | ||
@@ -357,7 +381,6 @@ static void __init of_register_i2c_devices(struct device_node *adap_node, int bu | |||
357 | if (of_find_i2c_driver(node, &info) < 0) | 381 | if (of_find_i2c_driver(node, &info) < 0) |
358 | continue; | 382 | continue; |
359 | 383 | ||
360 | info.platform_data = NULL; | ||
361 | info.addr = *addr; | 384 | info.addr = *addr; |
362 | 385 | ||
363 | i2c_register_board_info(bus_num, &info, 1); | 386 | i2c_register_board_info(bus_num, &info, 1); |
@@ -648,6 +671,7 @@ err: | |||
648 | 671 | ||
649 | arch_initcall(fsl_usb_of_init); | 672 | arch_initcall(fsl_usb_of_init); |
650 | 673 | ||
674 | #ifndef CONFIG_PPC_CPM_NEW_BINDING | ||
651 | #ifdef CONFIG_CPM2 | 675 | #ifdef CONFIG_CPM2 |
652 | 676 | ||
653 | extern void init_scc_ioports(struct fs_uart_platform_info*); | 677 | extern void init_scc_ioports(struct fs_uart_platform_info*); |
@@ -1187,3 +1211,132 @@ err: | |||
1187 | arch_initcall(cpm_smc_uart_of_init); | 1211 | arch_initcall(cpm_smc_uart_of_init); |
1188 | 1212 | ||
1189 | #endif /* CONFIG_8xx */ | 1213 | #endif /* CONFIG_8xx */ |
1214 | #endif /* CONFIG_PPC_CPM_NEW_BINDING */ | ||
1215 | |||
1216 | int __init fsl_spi_init(struct spi_board_info *board_infos, | ||
1217 | unsigned int num_board_infos, | ||
1218 | void (*activate_cs)(u8 cs, u8 polarity), | ||
1219 | void (*deactivate_cs)(u8 cs, u8 polarity)) | ||
1220 | { | ||
1221 | struct device_node *np; | ||
1222 | unsigned int i; | ||
1223 | const u32 *sysclk; | ||
1224 | |||
1225 | /* SPI controller is either clocked from QE or SoC clock */ | ||
1226 | np = of_find_node_by_type(NULL, "qe"); | ||
1227 | if (!np) | ||
1228 | np = of_find_node_by_type(NULL, "soc"); | ||
1229 | |||
1230 | if (!np) | ||
1231 | return -ENODEV; | ||
1232 | |||
1233 | sysclk = of_get_property(np, "bus-frequency", NULL); | ||
1234 | if (!sysclk) | ||
1235 | return -ENODEV; | ||
1236 | |||
1237 | for (np = NULL, i = 1; | ||
1238 | (np = of_find_compatible_node(np, "spi", "fsl_spi")) != NULL; | ||
1239 | i++) { | ||
1240 | int ret = 0; | ||
1241 | unsigned int j; | ||
1242 | const void *prop; | ||
1243 | struct resource res[2]; | ||
1244 | struct platform_device *pdev; | ||
1245 | struct fsl_spi_platform_data pdata = { | ||
1246 | .activate_cs = activate_cs, | ||
1247 | .deactivate_cs = deactivate_cs, | ||
1248 | }; | ||
1249 | |||
1250 | memset(res, 0, sizeof(res)); | ||
1251 | |||
1252 | pdata.sysclk = *sysclk; | ||
1253 | |||
1254 | prop = of_get_property(np, "reg", NULL); | ||
1255 | if (!prop) | ||
1256 | goto err; | ||
1257 | pdata.bus_num = *(u32 *)prop; | ||
1258 | |||
1259 | prop = of_get_property(np, "mode", NULL); | ||
1260 | if (prop && !strcmp(prop, "cpu-qe")) | ||
1261 | pdata.qe_mode = 1; | ||
1262 | |||
1263 | for (j = 0; j < num_board_infos; j++) { | ||
1264 | if (board_infos[j].bus_num == pdata.bus_num) | ||
1265 | pdata.max_chipselect++; | ||
1266 | } | ||
1267 | |||
1268 | if (!pdata.max_chipselect) | ||
1269 | goto err; | ||
1270 | |||
1271 | ret = of_address_to_resource(np, 0, &res[0]); | ||
1272 | if (ret) | ||
1273 | goto err; | ||
1274 | |||
1275 | ret = of_irq_to_resource(np, 0, &res[1]); | ||
1276 | if (ret == NO_IRQ) | ||
1277 | goto err; | ||
1278 | |||
1279 | pdev = platform_device_alloc("mpc83xx_spi", i); | ||
1280 | if (!pdev) | ||
1281 | goto err; | ||
1282 | |||
1283 | ret = platform_device_add_data(pdev, &pdata, sizeof(pdata)); | ||
1284 | if (ret) | ||
1285 | goto unreg; | ||
1286 | |||
1287 | ret = platform_device_add_resources(pdev, res, | ||
1288 | ARRAY_SIZE(res)); | ||
1289 | if (ret) | ||
1290 | goto unreg; | ||
1291 | |||
1292 | ret = platform_device_register(pdev); | ||
1293 | if (ret) | ||
1294 | goto unreg; | ||
1295 | |||
1296 | continue; | ||
1297 | unreg: | ||
1298 | platform_device_del(pdev); | ||
1299 | err: | ||
1300 | continue; | ||
1301 | } | ||
1302 | |||
1303 | return spi_register_board_info(board_infos, num_board_infos); | ||
1304 | } | ||
1305 | |||
1306 | #if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) | ||
1307 | static __be32 __iomem *rstcr; | ||
1308 | |||
1309 | static int __init setup_rstcr(void) | ||
1310 | { | ||
1311 | struct device_node *np; | ||
1312 | np = of_find_node_by_name(NULL, "global-utilities"); | ||
1313 | if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) { | ||
1314 | const u32 *prop = of_get_property(np, "reg", NULL); | ||
1315 | if (prop) { | ||
1316 | /* map reset control register | ||
1317 | * 0xE00B0 is offset of reset control register | ||
1318 | */ | ||
1319 | rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff); | ||
1320 | if (!rstcr) | ||
1321 | printk (KERN_EMERG "Error: reset control " | ||
1322 | "register not mapped!\n"); | ||
1323 | } | ||
1324 | } else | ||
1325 | printk (KERN_INFO "rstcr compatible register does not exist!\n"); | ||
1326 | if (np) | ||
1327 | of_node_put(np); | ||
1328 | return 0; | ||
1329 | } | ||
1330 | |||
1331 | arch_initcall(setup_rstcr); | ||
1332 | |||
1333 | void fsl_rstcr_restart(char *cmd) | ||
1334 | { | ||
1335 | local_irq_disable(); | ||
1336 | if (rstcr) | ||
1337 | /* set reset control register */ | ||
1338 | out_be32(rstcr, 0x2); /* HRESET_REQ */ | ||
1339 | |||
1340 | while (1) ; | ||
1341 | } | ||
1342 | #endif | ||