Lines Matching +full:bcm2835 +full:- +full:firmware
1 // SPDX-License-Identifier: GPL-2.0+
3 * Raspberry Pi driver for firmware controlled clocks
5 * Even though clk-bcm2835 provides an interface to the hardware registers for
6 * the system clocks we've had to factor out 'pllb' as the firmware 'owns' it.
8 * over-temperature and under-voltage protections provided by the firmware.
14 #include <linux/clk-provider.h>
19 #include <soc/bcm2835/raspberrypi-firmware.h>
53 [RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = "pixel-bvb",
61 struct rpi_firmware *firmware; member
74 * Structure of the message passed to Raspberry Pi's firmware in order to
80 * use the firmware interface as the firmware ultimately takes care of
84 * For more information on the firmware interface check:
85 * https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
93 static int raspberrypi_clock_property(struct rpi_firmware *firmware, in raspberrypi_clock_property() argument
98 .id = cpu_to_le32(data->id), in raspberrypi_clock_property()
104 ret = rpi_firmware_property(firmware, tag, &msg, sizeof(msg)); in raspberrypi_clock_property()
117 struct raspberrypi_clk *rpi = data->rpi; in raspberrypi_fw_is_prepared()
121 ret = raspberrypi_clock_property(rpi->firmware, data, in raspberrypi_fw_is_prepared()
135 struct raspberrypi_clk *rpi = data->rpi; in raspberrypi_fw_get_rate()
139 ret = raspberrypi_clock_property(rpi->firmware, data, in raspberrypi_fw_get_rate()
152 struct raspberrypi_clk *rpi = data->rpi; in raspberrypi_fw_set_rate()
156 ret = raspberrypi_clock_property(rpi->firmware, data, in raspberrypi_fw_set_rate()
159 dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d", in raspberrypi_fw_set_rate()
169 * The firmware will do the rounding but that isn't part of in raspberrypi_fw_dumb_determine_rate()
170 * the interface with the firmware, so we just do our best in raspberrypi_fw_dumb_determine_rate()
173 req->rate = clamp(req->rate, req->min_rate, req->max_rate); in raspberrypi_fw_dumb_determine_rate()
193 data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL); in raspberrypi_clk_register()
195 return ERR_PTR(-ENOMEM); in raspberrypi_clk_register()
196 data->rpi = rpi; in raspberrypi_clk_register()
197 data->id = id; in raspberrypi_clk_register()
199 init.name = devm_kasprintf(rpi->dev, GFP_KERNEL, in raspberrypi_clk_register()
200 "fw-clk-%s", in raspberrypi_clk_register()
205 data->hw.init = &init; in raspberrypi_clk_register()
207 ret = raspberrypi_clock_property(rpi->firmware, data, in raspberrypi_clk_register()
211 dev_err(rpi->dev, "Failed to get clock %d min freq: %d", in raspberrypi_clk_register()
216 ret = raspberrypi_clock_property(rpi->firmware, data, in raspberrypi_clk_register()
220 dev_err(rpi->dev, "Failed to get clock %d max freq: %d\n", in raspberrypi_clk_register()
225 ret = devm_clk_hw_register(rpi->dev, &data->hw); in raspberrypi_clk_register()
229 clk_hw_set_rate_range(&data->hw, min_rate, max_rate); in raspberrypi_clk_register()
232 ret = devm_clk_hw_register_clkdev(rpi->dev, &data->hw, in raspberrypi_clk_register()
235 dev_err(rpi->dev, "Failed to initialize clkdev\n"); in raspberrypi_clk_register()
240 return &data->hw; in raspberrypi_clk_register()
254 clks = devm_kcalloc(rpi->dev, in raspberrypi_discover_clocks()
258 return -ENOMEM; in raspberrypi_discover_clocks()
260 ret = rpi_firmware_property(rpi->firmware, RPI_FIRMWARE_GET_CLOCKS, in raspberrypi_discover_clocks()
266 while (clks->id) { in raspberrypi_discover_clocks()
269 switch (clks->id) { in raspberrypi_discover_clocks()
275 hw = raspberrypi_clk_register(rpi, clks->parent, in raspberrypi_discover_clocks()
276 clks->id); in raspberrypi_discover_clocks()
280 data->hws[clks->id] = hw; in raspberrypi_discover_clocks()
281 data->num = clks->id + 1; in raspberrypi_discover_clocks()
297 struct device *dev = &pdev->dev; in raspberrypi_clk_probe()
298 struct rpi_firmware *firmware; in raspberrypi_clk_probe() local
303 * We can be probed either through the an old-fashioned in raspberrypi_clk_probe()
305 * child of the firmware node. Handle both cases. in raspberrypi_clk_probe()
307 if (dev->of_node) in raspberrypi_clk_probe()
308 firmware_node = of_get_parent(dev->of_node); in raspberrypi_clk_probe()
311 "raspberrypi,bcm2835-firmware"); in raspberrypi_clk_probe()
313 dev_err(dev, "Missing firmware node\n"); in raspberrypi_clk_probe()
314 return -ENOENT; in raspberrypi_clk_probe()
317 firmware = rpi_firmware_get(firmware_node); in raspberrypi_clk_probe()
319 if (!firmware) in raspberrypi_clk_probe()
320 return -EPROBE_DEFER; in raspberrypi_clk_probe()
324 return -ENOMEM; in raspberrypi_clk_probe()
326 rpi->dev = dev; in raspberrypi_clk_probe()
327 rpi->firmware = firmware; in raspberrypi_clk_probe()
334 return -ENOMEM; in raspberrypi_clk_probe()
345 rpi->cpufreq = platform_device_register_data(dev, "raspberrypi-cpufreq", in raspberrypi_clk_probe()
346 -1, NULL, 0); in raspberrypi_clk_probe()
355 platform_device_unregister(rpi->cpufreq); in raspberrypi_clk_remove()
361 { .compatible = "raspberrypi,firmware-clocks" },
368 .name = "raspberrypi-clk",
377 MODULE_DESCRIPTION("Raspberry Pi firmware clock driver");
379 MODULE_ALIAS("platform:raspberrypi-clk");