diff options
author | Vitaly Bordug <vbordug@ru.mvista.com> | 2007-01-24 14:41:15 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-02-06 22:03:17 -0500 |
commit | 88bdc6f061cfb4579d2327fd457d4b7807525a0e (patch) | |
tree | 809bc55c9305d66d66c4546fe7991ae8e625a5cd /arch/powerpc/sysdev | |
parent | 5902ebce22fa5a1ac833565dbc4fde7e8a1bc737 (diff) |
[POWERPC] 8xx: platform related changes to the fsl_soc
Added 8xx SoC peripherials: fec for Ethernet and smc for UARTs.
Ordinary routines to extract values from the device tree and insert
respective platform devices
Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/fsl_soc.c | 274 |
1 files changed, 272 insertions, 2 deletions
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index ad31e56e892b..9f2a9a444bfb 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -38,7 +38,8 @@ | |||
38 | #include <asm/cpm2.h> | 38 | #include <asm/cpm2.h> |
39 | 39 | ||
40 | extern void init_fcc_ioports(struct fs_platform_info*); | 40 | extern void init_fcc_ioports(struct fs_platform_info*); |
41 | extern void init_scc_ioports(struct fs_uart_platform_info*); | 41 | extern void init_fec_ioports(struct fs_platform_info*); |
42 | extern void init_smc_ioports(struct fs_uart_platform_info*); | ||
42 | static phys_addr_t immrbase = -1; | 43 | static phys_addr_t immrbase = -1; |
43 | 44 | ||
44 | phys_addr_t get_immrbase(void) | 45 | phys_addr_t get_immrbase(void) |
@@ -63,7 +64,7 @@ phys_addr_t get_immrbase(void) | |||
63 | 64 | ||
64 | EXPORT_SYMBOL(get_immrbase); | 65 | EXPORT_SYMBOL(get_immrbase); |
65 | 66 | ||
66 | #ifdef CONFIG_CPM2 | 67 | #if defined(CONFIG_CPM2) || defined(CONFIG_8xx) |
67 | 68 | ||
68 | static u32 brgfreq = -1; | 69 | static u32 brgfreq = -1; |
69 | 70 | ||
@@ -544,6 +545,8 @@ arch_initcall(fsl_usb_of_init); | |||
544 | 545 | ||
545 | #ifdef CONFIG_CPM2 | 546 | #ifdef CONFIG_CPM2 |
546 | 547 | ||
548 | extern void init_scc_ioports(struct fs_uart_platform_info*); | ||
549 | |||
547 | static const char fcc_regs[] = "fcc_regs"; | 550 | static const char fcc_regs[] = "fcc_regs"; |
548 | static const char fcc_regs_c[] = "fcc_regs_c"; | 551 | static const char fcc_regs_c[] = "fcc_regs_c"; |
549 | static const char fcc_pram[] = "fcc_pram"; | 552 | static const char fcc_pram[] = "fcc_pram"; |
@@ -792,3 +795,270 @@ err: | |||
792 | 795 | ||
793 | arch_initcall(cpm_uart_of_init); | 796 | arch_initcall(cpm_uart_of_init); |
794 | #endif /* CONFIG_CPM2 */ | 797 | #endif /* CONFIG_CPM2 */ |
798 | |||
799 | #ifdef CONFIG_8xx | ||
800 | |||
801 | extern void init_scc_ioports(struct fs_platform_info*); | ||
802 | extern int platform_device_skip(char *model, int id); | ||
803 | |||
804 | static int __init fs_enet_mdio_of_init(void) | ||
805 | { | ||
806 | struct device_node *np; | ||
807 | unsigned int i; | ||
808 | struct platform_device *mdio_dev; | ||
809 | struct resource res; | ||
810 | int ret; | ||
811 | |||
812 | for (np = NULL, i = 0; | ||
813 | (np = of_find_compatible_node(np, "mdio", "fs_enet")) != NULL; | ||
814 | i++) { | ||
815 | struct fs_mii_fec_platform_info mdio_data; | ||
816 | |||
817 | memset(&res, 0, sizeof(res)); | ||
818 | memset(&mdio_data, 0, sizeof(mdio_data)); | ||
819 | |||
820 | ret = of_address_to_resource(np, 0, &res); | ||
821 | if (ret) | ||
822 | goto err; | ||
823 | |||
824 | mdio_dev = | ||
825 | platform_device_register_simple("fsl-cpm-fec-mdio", | ||
826 | res.start, &res, 1); | ||
827 | if (IS_ERR(mdio_dev)) { | ||
828 | ret = PTR_ERR(mdio_dev); | ||
829 | goto err; | ||
830 | } | ||
831 | |||
832 | mdio_data.mii_speed = ((((ppc_proc_freq + 4999999) / 2500000) / 2) & 0x3F) << 1; | ||
833 | |||
834 | ret = | ||
835 | platform_device_add_data(mdio_dev, &mdio_data, | ||
836 | sizeof(struct fs_mii_fec_platform_info)); | ||
837 | if (ret) | ||
838 | goto unreg; | ||
839 | } | ||
840 | return 0; | ||
841 | |||
842 | unreg: | ||
843 | platform_device_unregister(mdio_dev); | ||
844 | err: | ||
845 | return ret; | ||
846 | } | ||
847 | |||
848 | arch_initcall(fs_enet_mdio_of_init); | ||
849 | |||
850 | static const char *enet_regs = "regs"; | ||
851 | static const char *enet_pram = "pram"; | ||
852 | static const char *enet_irq = "interrupt"; | ||
853 | static char bus_id[9][BUS_ID_SIZE]; | ||
854 | |||
855 | static int __init fs_enet_of_init(void) | ||
856 | { | ||
857 | struct device_node *np; | ||
858 | unsigned int i; | ||
859 | struct platform_device *fs_enet_dev = NULL; | ||
860 | struct resource res; | ||
861 | int ret; | ||
862 | |||
863 | for (np = NULL, i = 0; | ||
864 | (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL; | ||
865 | i++) { | ||
866 | struct resource r[4]; | ||
867 | struct device_node *phy = NULL, *mdio = NULL; | ||
868 | struct fs_platform_info fs_enet_data; | ||
869 | unsigned int *id, *phy_addr; | ||
870 | void *mac_addr; | ||
871 | phandle *ph; | ||
872 | char *model; | ||
873 | |||
874 | memset(r, 0, sizeof(r)); | ||
875 | memset(&fs_enet_data, 0, sizeof(fs_enet_data)); | ||
876 | |||
877 | model = (char *)get_property(np, "model", NULL); | ||
878 | if (model == NULL) { | ||
879 | ret = -ENODEV; | ||
880 | goto unreg; | ||
881 | } | ||
882 | |||
883 | id = (u32 *) get_property(np, "device-id", NULL); | ||
884 | fs_enet_data.fs_no = *id; | ||
885 | |||
886 | if (platform_device_skip(model, *id)) | ||
887 | continue; | ||
888 | |||
889 | ret = of_address_to_resource(np, 0, &r[0]); | ||
890 | if (ret) | ||
891 | goto err; | ||
892 | r[0].name = enet_regs; | ||
893 | |||
894 | mac_addr = (void *)get_property(np, "mac-address", NULL); | ||
895 | memcpy(fs_enet_data.macaddr, mac_addr, 6); | ||
896 | |||
897 | ph = (phandle *) get_property(np, "phy-handle", NULL); | ||
898 | if (ph != NULL) | ||
899 | phy = of_find_node_by_phandle(*ph); | ||
900 | |||
901 | if (phy != NULL) { | ||
902 | phy_addr = (u32 *) get_property(phy, "reg", NULL); | ||
903 | fs_enet_data.phy_addr = *phy_addr; | ||
904 | fs_enet_data.has_phy = 1; | ||
905 | |||
906 | mdio = of_get_parent(phy); | ||
907 | ret = of_address_to_resource(mdio, 0, &res); | ||
908 | if (ret) { | ||
909 | of_node_put(phy); | ||
910 | of_node_put(mdio); | ||
911 | goto unreg; | ||
912 | } | ||
913 | } | ||
914 | |||
915 | model = (char*)get_property(np, "model", NULL); | ||
916 | strcpy(fs_enet_data.fs_type, model); | ||
917 | |||
918 | if (strstr(model, "FEC")) { | ||
919 | r[1].start = r[1].end = irq_of_parse_and_map(np, 0); | ||
920 | r[1].flags = IORESOURCE_IRQ; | ||
921 | r[1].name = enet_irq; | ||
922 | |||
923 | fs_enet_dev = | ||
924 | platform_device_register_simple("fsl-cpm-fec", i, &r[0], 2); | ||
925 | |||
926 | if (IS_ERR(fs_enet_dev)) { | ||
927 | ret = PTR_ERR(fs_enet_dev); | ||
928 | goto err; | ||
929 | } | ||
930 | |||
931 | fs_enet_data.rx_ring = 128; | ||
932 | fs_enet_data.tx_ring = 16; | ||
933 | fs_enet_data.rx_copybreak = 240; | ||
934 | fs_enet_data.use_napi = 1; | ||
935 | fs_enet_data.napi_weight = 17; | ||
936 | |||
937 | snprintf((char*)&bus_id[i], BUS_ID_SIZE, "%x:%02x", | ||
938 | (u32)res.start, fs_enet_data.phy_addr); | ||
939 | fs_enet_data.bus_id = (char*)&bus_id[i]; | ||
940 | fs_enet_data.init_ioports = init_fec_ioports; | ||
941 | } | ||
942 | if (strstr(model, "SCC")) { | ||
943 | ret = of_address_to_resource(np, 1, &r[1]); | ||
944 | if (ret) | ||
945 | goto err; | ||
946 | r[1].name = enet_pram; | ||
947 | |||
948 | r[2].start = r[2].end = irq_of_parse_and_map(np, 0); | ||
949 | r[2].flags = IORESOURCE_IRQ; | ||
950 | r[2].name = enet_irq; | ||
951 | |||
952 | fs_enet_dev = | ||
953 | platform_device_register_simple("fsl-cpm-scc", i, &r[0], 3); | ||
954 | |||
955 | if (IS_ERR(fs_enet_dev)) { | ||
956 | ret = PTR_ERR(fs_enet_dev); | ||
957 | goto err; | ||
958 | } | ||
959 | |||
960 | fs_enet_data.rx_ring = 64; | ||
961 | fs_enet_data.tx_ring = 8; | ||
962 | fs_enet_data.rx_copybreak = 240; | ||
963 | fs_enet_data.use_napi = 1; | ||
964 | fs_enet_data.napi_weight = 17; | ||
965 | |||
966 | snprintf((char*)&bus_id[i], BUS_ID_SIZE, "%s", "fixed@10:1"); | ||
967 | fs_enet_data.bus_id = (char*)&bus_id[i]; | ||
968 | fs_enet_data.init_ioports = init_scc_ioports; | ||
969 | } | ||
970 | |||
971 | of_node_put(phy); | ||
972 | of_node_put(mdio); | ||
973 | |||
974 | ret = platform_device_add_data(fs_enet_dev, &fs_enet_data, | ||
975 | sizeof(struct | ||
976 | fs_platform_info)); | ||
977 | if (ret) | ||
978 | goto unreg; | ||
979 | } | ||
980 | return 0; | ||
981 | |||
982 | unreg: | ||
983 | platform_device_unregister(fs_enet_dev); | ||
984 | err: | ||
985 | return ret; | ||
986 | } | ||
987 | |||
988 | arch_initcall(fs_enet_of_init); | ||
989 | |||
990 | |||
991 | static const char *smc_regs = "regs"; | ||
992 | static const char *smc_pram = "pram"; | ||
993 | |||
994 | static int __init cpm_smc_uart_of_init(void) | ||
995 | { | ||
996 | struct device_node *np; | ||
997 | unsigned int i; | ||
998 | struct platform_device *cpm_uart_dev; | ||
999 | int ret; | ||
1000 | |||
1001 | for (np = NULL, i = 0; | ||
1002 | (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL; | ||
1003 | i++) { | ||
1004 | struct resource r[3]; | ||
1005 | struct fs_uart_platform_info cpm_uart_data; | ||
1006 | int *id; | ||
1007 | char *model; | ||
1008 | |||
1009 | memset(r, 0, sizeof(r)); | ||
1010 | memset(&cpm_uart_data, 0, sizeof(cpm_uart_data)); | ||
1011 | |||
1012 | ret = of_address_to_resource(np, 0, &r[0]); | ||
1013 | if (ret) | ||
1014 | goto err; | ||
1015 | |||
1016 | r[0].name = smc_regs; | ||
1017 | |||
1018 | ret = of_address_to_resource(np, 1, &r[1]); | ||
1019 | if (ret) | ||
1020 | goto err; | ||
1021 | r[1].name = smc_pram; | ||
1022 | |||
1023 | r[2].start = r[2].end = irq_of_parse_and_map(np, 0); | ||
1024 | r[2].flags = IORESOURCE_IRQ; | ||
1025 | |||
1026 | cpm_uart_dev = | ||
1027 | platform_device_register_simple("fsl-cpm-smc:uart", i, &r[0], 3); | ||
1028 | |||
1029 | if (IS_ERR(cpm_uart_dev)) { | ||
1030 | ret = PTR_ERR(cpm_uart_dev); | ||
1031 | goto err; | ||
1032 | } | ||
1033 | |||
1034 | model = (char*)get_property(np, "model", NULL); | ||
1035 | strcpy(cpm_uart_data.fs_type, model); | ||
1036 | |||
1037 | id = (int*)get_property(np, "device-id", NULL); | ||
1038 | cpm_uart_data.fs_no = *id; | ||
1039 | cpm_uart_data.uart_clk = ppc_proc_freq; | ||
1040 | |||
1041 | cpm_uart_data.tx_num_fifo = 4; | ||
1042 | cpm_uart_data.tx_buf_size = 32; | ||
1043 | cpm_uart_data.rx_num_fifo = 4; | ||
1044 | cpm_uart_data.rx_buf_size = 32; | ||
1045 | |||
1046 | ret = | ||
1047 | platform_device_add_data(cpm_uart_dev, &cpm_uart_data, | ||
1048 | sizeof(struct | ||
1049 | fs_uart_platform_info)); | ||
1050 | if (ret) | ||
1051 | goto unreg; | ||
1052 | } | ||
1053 | |||
1054 | return 0; | ||
1055 | |||
1056 | unreg: | ||
1057 | platform_device_unregister(cpm_uart_dev); | ||
1058 | err: | ||
1059 | return ret; | ||
1060 | } | ||
1061 | |||
1062 | arch_initcall(cpm_smc_uart_of_init); | ||
1063 | |||
1064 | #endif /* CONFIG_8xx */ | ||