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.
6 * Copyright (C) 2012 John Crispin <blogic@phrozen.org>
7 * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
8 * Copyright (C) 2017 Hauke Mehrtens <hauke@hauke-m.de>
11 #include <linux/clk.h>
12 #include <linux/delay.h>
13 #include <linux/dma-mapping.h>
14 #include <linux/firmware.h>
15 #include <linux/mfd/syscon.h>
16 #include <linux/module.h>
17 #include <linux/reboot.h>
18 #include <linux/regmap.h>
19 #include <linux/reset.h>
20 #include <linux/of_device.h>
21 #include <linux/of_platform.h>
22 #include <linux/property.h>
23 #include <dt-bindings/mips/lantiq_rcu_gphy.h>
25 #include <lantiq_soc.h>
27 #define XRX200_GPHY_FW_ALIGN (16 * 1024)
29 struct xway_gphy_priv
{
30 struct clk
*gphy_clk_gate
;
31 struct reset_control
*gphy_reset
;
32 struct reset_control
*gphy_reset2
;
33 struct notifier_block gphy_reboot_nb
;
34 void __iomem
*membase
;
38 struct xway_gphy_match_data
{
39 char *fe_firmware_name
;
40 char *ge_firmware_name
;
43 static const struct xway_gphy_match_data xrx200a1x_gphy_data
= {
44 .fe_firmware_name
= "lantiq/xrx200_phy22f_a14.bin",
45 .ge_firmware_name
= "lantiq/xrx200_phy11g_a14.bin",
48 static const struct xway_gphy_match_data xrx200a2x_gphy_data
= {
49 .fe_firmware_name
= "lantiq/xrx200_phy22f_a22.bin",
50 .ge_firmware_name
= "lantiq/xrx200_phy11g_a22.bin",
53 static const struct xway_gphy_match_data xrx300_gphy_data
= {
54 .fe_firmware_name
= "lantiq/xrx300_phy22f_a21.bin",
55 .ge_firmware_name
= "lantiq/xrx300_phy11g_a21.bin",
58 static const struct of_device_id xway_gphy_match
[] = {
59 { .compatible
= "lantiq,xrx200a1x-gphy", .data
= &xrx200a1x_gphy_data
},
60 { .compatible
= "lantiq,xrx200a2x-gphy", .data
= &xrx200a2x_gphy_data
},
61 { .compatible
= "lantiq,xrx300-gphy", .data
= &xrx300_gphy_data
},
62 { .compatible
= "lantiq,xrx330-gphy", .data
= &xrx300_gphy_data
},
65 MODULE_DEVICE_TABLE(of
, xway_gphy_match
);
67 static struct xway_gphy_priv
*to_xway_gphy_priv(struct notifier_block
*nb
)
69 return container_of(nb
, struct xway_gphy_priv
, gphy_reboot_nb
);
72 static int xway_gphy_reboot_notify(struct notifier_block
*reboot_nb
,
73 unsigned long code
, void *unused
)
75 struct xway_gphy_priv
*priv
= to_xway_gphy_priv(reboot_nb
);
78 reset_control_assert(priv
->gphy_reset
);
79 reset_control_assert(priv
->gphy_reset2
);
85 static int xway_gphy_load(struct device
*dev
, struct xway_gphy_priv
*priv
,
88 const struct firmware
*fw
;
94 ret
= request_firmware(&fw
, priv
->fw_name
, dev
);
96 dev_err(dev
, "failed to load firmware: %s, error: %i\n",
102 * GPHY cores need the firmware code in a persistent and contiguous
103 * memory area with a 16 kB boundary aligned start address.
105 size
= fw
->size
+ XRX200_GPHY_FW_ALIGN
;
107 fw_addr
= dmam_alloc_coherent(dev
, size
, &dma_addr
, GFP_KERNEL
);
109 fw_addr
= PTR_ALIGN(fw_addr
, XRX200_GPHY_FW_ALIGN
);
110 *dev_addr
= ALIGN(dma_addr
, XRX200_GPHY_FW_ALIGN
);
111 memcpy(fw_addr
, fw
->data
, fw
->size
);
113 dev_err(dev
, "failed to alloc firmware memory\n");
117 release_firmware(fw
);
122 static int xway_gphy_of_probe(struct platform_device
*pdev
,
123 struct xway_gphy_priv
*priv
)
125 struct device
*dev
= &pdev
->dev
;
126 const struct xway_gphy_match_data
*gphy_fw_name_cfg
;
129 struct resource
*res_gphy
;
131 gphy_fw_name_cfg
= of_device_get_match_data(dev
);
133 priv
->gphy_clk_gate
= devm_clk_get(dev
, NULL
);
134 if (IS_ERR(priv
->gphy_clk_gate
)) {
135 dev_err(dev
, "Failed to lookup gate clock\n");
136 return PTR_ERR(priv
->gphy_clk_gate
);
139 res_gphy
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
140 priv
->membase
= devm_ioremap_resource(dev
, res_gphy
);
141 if (IS_ERR(priv
->membase
))
142 return PTR_ERR(priv
->membase
);
144 priv
->gphy_reset
= devm_reset_control_get(dev
, "gphy");
145 if (IS_ERR(priv
->gphy_reset
)) {
146 if (PTR_ERR(priv
->gphy_reset
) != -EPROBE_DEFER
)
147 dev_err(dev
, "Failed to lookup gphy reset\n");
148 return PTR_ERR(priv
->gphy_reset
);
151 priv
->gphy_reset2
= devm_reset_control_get_optional(dev
, "gphy2");
152 if (IS_ERR(priv
->gphy_reset2
))
153 return PTR_ERR(priv
->gphy_reset2
);
155 ret
= device_property_read_u32(dev
, "lantiq,gphy-mode", &gphy_mode
);
156 /* Default to GE mode */
158 gphy_mode
= GPHY_MODE_GE
;
162 priv
->fw_name
= gphy_fw_name_cfg
->fe_firmware_name
;
165 priv
->fw_name
= gphy_fw_name_cfg
->ge_firmware_name
;
168 dev_err(dev
, "Unknown GPHY mode %d\n", gphy_mode
);
175 static int xway_gphy_probe(struct platform_device
*pdev
)
177 struct device
*dev
= &pdev
->dev
;
178 struct xway_gphy_priv
*priv
;
179 dma_addr_t fw_addr
= 0;
182 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
186 ret
= xway_gphy_of_probe(pdev
, priv
);
190 ret
= clk_prepare_enable(priv
->gphy_clk_gate
);
194 ret
= xway_gphy_load(dev
, priv
, &fw_addr
);
196 clk_disable_unprepare(priv
->gphy_clk_gate
);
200 reset_control_assert(priv
->gphy_reset
);
201 reset_control_assert(priv
->gphy_reset2
);
203 iowrite32be(fw_addr
, priv
->membase
);
205 reset_control_deassert(priv
->gphy_reset
);
206 reset_control_deassert(priv
->gphy_reset2
);
208 /* assert the gphy reset because it can hang after a reboot: */
209 priv
->gphy_reboot_nb
.notifier_call
= xway_gphy_reboot_notify
;
210 priv
->gphy_reboot_nb
.priority
= -1;
212 ret
= register_reboot_notifier(&priv
->gphy_reboot_nb
);
214 dev_warn(dev
, "Failed to register reboot notifier\n");
216 platform_set_drvdata(pdev
, priv
);
221 static int xway_gphy_remove(struct platform_device
*pdev
)
223 struct device
*dev
= &pdev
->dev
;
224 struct xway_gphy_priv
*priv
= platform_get_drvdata(pdev
);
227 reset_control_assert(priv
->gphy_reset
);
228 reset_control_assert(priv
->gphy_reset2
);
230 iowrite32be(0, priv
->membase
);
232 clk_disable_unprepare(priv
->gphy_clk_gate
);
234 ret
= unregister_reboot_notifier(&priv
->gphy_reboot_nb
);
236 dev_warn(dev
, "Failed to unregister reboot notifier\n");
241 static struct platform_driver xway_gphy_driver
= {
242 .probe
= xway_gphy_probe
,
243 .remove
= xway_gphy_remove
,
245 .name
= "xway-rcu-gphy",
246 .of_match_table
= xway_gphy_match
,
250 module_platform_driver(xway_gphy_driver
);
252 MODULE_FIRMWARE("lantiq/xrx300_phy11g_a21.bin");
253 MODULE_FIRMWARE("lantiq/xrx300_phy22f_a21.bin");
254 MODULE_FIRMWARE("lantiq/xrx200_phy11g_a14.bin");
255 MODULE_FIRMWARE("lantiq/xrx200_phy11g_a22.bin");
256 MODULE_FIRMWARE("lantiq/xrx200_phy22f_a14.bin");
257 MODULE_FIRMWARE("lantiq/xrx200_phy22f_a22.bin");
258 MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
259 MODULE_DESCRIPTION("Lantiq XWAY GPHY Firmware Loader");
260 MODULE_LICENSE("GPL");