diff options
author | John Crispin <blogic@openwrt.org> | 2012-10-22 01:52:50 -0400 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2012-11-11 12:47:41 -0500 |
commit | 0224cde212df4abf251f89c3724a800b1949a774 (patch) | |
tree | 8b842ccc1959188d4b61bdabb46b9df2d2890aa3 /arch/mips/lantiq | |
parent | af14a456c58c153c6d761e6c0af48157692b52ad (diff) |
MIPS: lantiq: adds GPHY firmware loader
The internal GPHYs need a firmware blob to function properly. This patch adds
the code needed to request the blob and load it to the PHY.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4523
Diffstat (limited to 'arch/mips/lantiq')
-rw-r--r-- | arch/mips/lantiq/Kconfig | 4 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/xrx200_phy_fw.c | 97 |
3 files changed, 103 insertions, 0 deletions
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig index d84f361f1e45..c0021912131e 100644 --- a/arch/mips/lantiq/Kconfig +++ b/arch/mips/lantiq/Kconfig | |||
@@ -36,4 +36,8 @@ config PCI_LANTIQ | |||
36 | bool "PCI Support" | 36 | bool "PCI Support" |
37 | depends on SOC_XWAY && PCI | 37 | depends on SOC_XWAY && PCI |
38 | 38 | ||
39 | config XRX200_PHY_FW | ||
40 | bool "XRX200 PHY firmware loader" | ||
41 | depends on SOC_XWAY | ||
42 | |||
39 | endif | 43 | endif |
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile index 70a58c747bd0..7a13660d630d 100644 --- a/arch/mips/lantiq/xway/Makefile +++ b/arch/mips/lantiq/xway/Makefile | |||
@@ -1 +1,3 @@ | |||
1 | obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o | 1 | obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o |
2 | |||
3 | obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o | ||
diff --git a/arch/mips/lantiq/xway/xrx200_phy_fw.c b/arch/mips/lantiq/xway/xrx200_phy_fw.c new file mode 100644 index 000000000000..fe808bf5366d --- /dev/null +++ b/arch/mips/lantiq/xway/xrx200_phy_fw.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License version 2 as published | ||
4 | * by the Free Software Foundation. | ||
5 | * | ||
6 | * Copyright (C) 2012 John Crispin <blogic@openwrt.org> | ||
7 | */ | ||
8 | |||
9 | #include <linux/delay.h> | ||
10 | #include <linux/dma-mapping.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/firmware.h> | ||
13 | #include <linux/of_platform.h> | ||
14 | |||
15 | #include <lantiq_soc.h> | ||
16 | |||
17 | #define XRX200_GPHY_FW_ALIGN (16 * 1024) | ||
18 | |||
19 | static dma_addr_t xway_gphy_load(struct platform_device *pdev) | ||
20 | { | ||
21 | const struct firmware *fw; | ||
22 | dma_addr_t dev_addr = 0; | ||
23 | const char *fw_name; | ||
24 | void *fw_addr; | ||
25 | size_t size; | ||
26 | |||
27 | if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) { | ||
28 | dev_err(&pdev->dev, "failed to load firmware filename\n"); | ||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | dev_info(&pdev->dev, "requesting %s\n", fw_name); | ||
33 | if (request_firmware(&fw, fw_name, &pdev->dev)) { | ||
34 | dev_err(&pdev->dev, "failed to load firmware: %s\n", fw_name); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | /* | ||
39 | * GPHY cores need the firmware code in a persistent and contiguous | ||
40 | * memory area with a 16 kB boundary aligned start address | ||
41 | */ | ||
42 | size = fw->size + XRX200_GPHY_FW_ALIGN; | ||
43 | |||
44 | fw_addr = dma_alloc_coherent(&pdev->dev, size, &dev_addr, GFP_KERNEL); | ||
45 | if (fw_addr) { | ||
46 | fw_addr = PTR_ALIGN(fw_addr, XRX200_GPHY_FW_ALIGN); | ||
47 | dev_addr = ALIGN(dev_addr, XRX200_GPHY_FW_ALIGN); | ||
48 | memcpy(fw_addr, fw->data, fw->size); | ||
49 | } else { | ||
50 | dev_err(&pdev->dev, "failed to alloc firmware memory\n"); | ||
51 | } | ||
52 | |||
53 | release_firmware(fw); | ||
54 | return dev_addr; | ||
55 | } | ||
56 | |||
57 | static int __devinit xway_phy_fw_probe(struct platform_device *pdev) | ||
58 | { | ||
59 | dma_addr_t fw_addr; | ||
60 | struct property *pp; | ||
61 | unsigned char *phyids; | ||
62 | int i, ret = 0; | ||
63 | |||
64 | fw_addr = xway_gphy_load(pdev); | ||
65 | if (!fw_addr) | ||
66 | return -EINVAL; | ||
67 | pp = of_find_property(pdev->dev.of_node, "phys", NULL); | ||
68 | if (!pp) | ||
69 | return -ENOENT; | ||
70 | phyids = pp->value; | ||
71 | for (i = 0; i < pp->length && !ret; i++) | ||
72 | ret = xrx200_gphy_boot(&pdev->dev, phyids[i], fw_addr); | ||
73 | if (!ret) | ||
74 | mdelay(100); | ||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | static const struct of_device_id xway_phy_match[] = { | ||
79 | { .compatible = "lantiq,phy-xrx200" }, | ||
80 | {}, | ||
81 | }; | ||
82 | MODULE_DEVICE_TABLE(of, xway_phy_match); | ||
83 | |||
84 | static struct platform_driver xway_phy_driver = { | ||
85 | .probe = xway_phy_fw_probe, | ||
86 | .driver = { | ||
87 | .name = "phy-xrx200", | ||
88 | .owner = THIS_MODULE, | ||
89 | .of_match_table = xway_phy_match, | ||
90 | }, | ||
91 | }; | ||
92 | |||
93 | module_platform_driver(xway_phy_driver); | ||
94 | |||
95 | MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); | ||
96 | MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader"); | ||
97 | MODULE_LICENSE("GPL"); | ||