Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Raspberry Pi driver for firmware controlled clocks
0004  *
0005  * Even though clk-bcm2835 provides an interface to the hardware registers for
0006  * the system clocks we've had to factor out 'pllb' as the firmware 'owns' it.
0007  * We're not allowed to change it directly as we might race with the
0008  * over-temperature and under-voltage protections provided by the firmware.
0009  *
0010  * Copyright (C) 2019 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
0011  */
0012 
0013 #include <linux/clkdev.h>
0014 #include <linux/clk-provider.h>
0015 #include <linux/io.h>
0016 #include <linux/module.h>
0017 #include <linux/platform_device.h>
0018 
0019 #include <soc/bcm2835/raspberrypi-firmware.h>
0020 
0021 enum rpi_firmware_clk_id {
0022     RPI_FIRMWARE_EMMC_CLK_ID = 1,
0023     RPI_FIRMWARE_UART_CLK_ID,
0024     RPI_FIRMWARE_ARM_CLK_ID,
0025     RPI_FIRMWARE_CORE_CLK_ID,
0026     RPI_FIRMWARE_V3D_CLK_ID,
0027     RPI_FIRMWARE_H264_CLK_ID,
0028     RPI_FIRMWARE_ISP_CLK_ID,
0029     RPI_FIRMWARE_SDRAM_CLK_ID,
0030     RPI_FIRMWARE_PIXEL_CLK_ID,
0031     RPI_FIRMWARE_PWM_CLK_ID,
0032     RPI_FIRMWARE_HEVC_CLK_ID,
0033     RPI_FIRMWARE_EMMC2_CLK_ID,
0034     RPI_FIRMWARE_M2MC_CLK_ID,
0035     RPI_FIRMWARE_PIXEL_BVB_CLK_ID,
0036     RPI_FIRMWARE_NUM_CLK_ID,
0037 };
0038 
0039 static char *rpi_firmware_clk_names[] = {
0040     [RPI_FIRMWARE_EMMC_CLK_ID]  = "emmc",
0041     [RPI_FIRMWARE_UART_CLK_ID]  = "uart",
0042     [RPI_FIRMWARE_ARM_CLK_ID]   = "arm",
0043     [RPI_FIRMWARE_CORE_CLK_ID]  = "core",
0044     [RPI_FIRMWARE_V3D_CLK_ID]   = "v3d",
0045     [RPI_FIRMWARE_H264_CLK_ID]  = "h264",
0046     [RPI_FIRMWARE_ISP_CLK_ID]   = "isp",
0047     [RPI_FIRMWARE_SDRAM_CLK_ID] = "sdram",
0048     [RPI_FIRMWARE_PIXEL_CLK_ID] = "pixel",
0049     [RPI_FIRMWARE_PWM_CLK_ID]   = "pwm",
0050     [RPI_FIRMWARE_HEVC_CLK_ID]  = "hevc",
0051     [RPI_FIRMWARE_EMMC2_CLK_ID] = "emmc2",
0052     [RPI_FIRMWARE_M2MC_CLK_ID]  = "m2mc",
0053     [RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = "pixel-bvb",
0054 };
0055 
0056 #define RPI_FIRMWARE_STATE_ENABLE_BIT   BIT(0)
0057 #define RPI_FIRMWARE_STATE_WAIT_BIT BIT(1)
0058 
0059 struct raspberrypi_clk_variant;
0060 
0061 struct raspberrypi_clk {
0062     struct device *dev;
0063     struct rpi_firmware *firmware;
0064     struct platform_device *cpufreq;
0065 };
0066 
0067 struct raspberrypi_clk_data {
0068     struct clk_hw hw;
0069 
0070     unsigned int id;
0071     struct raspberrypi_clk_variant *variant;
0072 
0073     struct raspberrypi_clk *rpi;
0074 };
0075 
0076 struct raspberrypi_clk_variant {
0077     bool        export;
0078     char        *clkdev;
0079     unsigned long   min_rate;
0080     bool        minimize;
0081 };
0082 
0083 static struct raspberrypi_clk_variant
0084 raspberrypi_clk_variants[RPI_FIRMWARE_NUM_CLK_ID] = {
0085     [RPI_FIRMWARE_ARM_CLK_ID] = {
0086         .export = true,
0087         .clkdev = "cpu0",
0088     },
0089     [RPI_FIRMWARE_CORE_CLK_ID] = {
0090         .export = true,
0091 
0092         /*
0093          * The clock is shared between the HVS and the CSI
0094          * controllers, on the BCM2711 and will change depending
0095          * on the pixels composited on the HVS and the capture
0096          * resolution on Unicam.
0097          *
0098          * Since the rate can get quite large, and we need to
0099          * coordinate between both driver instances, let's
0100          * always use the minimum the drivers will let us.
0101          */
0102         .minimize = true,
0103     },
0104     [RPI_FIRMWARE_M2MC_CLK_ID] = {
0105         .export = true,
0106 
0107         /*
0108          * If we boot without any cable connected to any of the
0109          * HDMI connector, the firmware will skip the HSM
0110          * initialization and leave it with a rate of 0,
0111          * resulting in a bus lockup when we're accessing the
0112          * registers even if it's enabled.
0113          *
0114          * Let's put a sensible default so that we don't end up
0115          * in this situation.
0116          */
0117         .min_rate = 120000000,
0118 
0119         /*
0120          * The clock is shared between the two HDMI controllers
0121          * on the BCM2711 and will change depending on the
0122          * resolution output on each. Since the rate can get
0123          * quite large, and we need to coordinate between both
0124          * driver instances, let's always use the minimum the
0125          * drivers will let us.
0126          */
0127         .minimize = true,
0128     },
0129     [RPI_FIRMWARE_V3D_CLK_ID] = {
0130         .export = true,
0131     },
0132     [RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = {
0133         .export = true,
0134     },
0135 };
0136 
0137 /*
0138  * Structure of the message passed to Raspberry Pi's firmware in order to
0139  * change clock rates. The 'disable_turbo' option is only available to the ARM
0140  * clock (pllb) which we enable by default as turbo mode will alter multiple
0141  * clocks at once.
0142  *
0143  * Even though we're able to access the clock registers directly we're bound to
0144  * use the firmware interface as the firmware ultimately takes care of
0145  * mitigating overheating/undervoltage situations and we would be changing
0146  * frequencies behind his back.
0147  *
0148  * For more information on the firmware interface check:
0149  * https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
0150  */
0151 struct raspberrypi_firmware_prop {
0152     __le32 id;
0153     __le32 val;
0154     __le32 disable_turbo;
0155 } __packed;
0156 
0157 static int raspberrypi_clock_property(struct rpi_firmware *firmware,
0158                       const struct raspberrypi_clk_data *data,
0159                       u32 tag, u32 *val)
0160 {
0161     struct raspberrypi_firmware_prop msg = {
0162         .id = cpu_to_le32(data->id),
0163         .val = cpu_to_le32(*val),
0164         .disable_turbo = cpu_to_le32(1),
0165     };
0166     int ret;
0167 
0168     ret = rpi_firmware_property(firmware, tag, &msg, sizeof(msg));
0169     if (ret)
0170         return ret;
0171 
0172     *val = le32_to_cpu(msg.val);
0173 
0174     return 0;
0175 }
0176 
0177 static int raspberrypi_fw_is_prepared(struct clk_hw *hw)
0178 {
0179     struct raspberrypi_clk_data *data =
0180         container_of(hw, struct raspberrypi_clk_data, hw);
0181     struct raspberrypi_clk *rpi = data->rpi;
0182     u32 val = 0;
0183     int ret;
0184 
0185     ret = raspberrypi_clock_property(rpi->firmware, data,
0186                      RPI_FIRMWARE_GET_CLOCK_STATE, &val);
0187     if (ret)
0188         return 0;
0189 
0190     return !!(val & RPI_FIRMWARE_STATE_ENABLE_BIT);
0191 }
0192 
0193 
0194 static unsigned long raspberrypi_fw_get_rate(struct clk_hw *hw,
0195                          unsigned long parent_rate)
0196 {
0197     struct raspberrypi_clk_data *data =
0198         container_of(hw, struct raspberrypi_clk_data, hw);
0199     struct raspberrypi_clk *rpi = data->rpi;
0200     u32 val = 0;
0201     int ret;
0202 
0203     ret = raspberrypi_clock_property(rpi->firmware, data,
0204                      RPI_FIRMWARE_GET_CLOCK_RATE, &val);
0205     if (ret)
0206         return 0;
0207 
0208     return val;
0209 }
0210 
0211 static int raspberrypi_fw_set_rate(struct clk_hw *hw, unsigned long rate,
0212                    unsigned long parent_rate)
0213 {
0214     struct raspberrypi_clk_data *data =
0215         container_of(hw, struct raspberrypi_clk_data, hw);
0216     struct raspberrypi_clk *rpi = data->rpi;
0217     u32 _rate = rate;
0218     int ret;
0219 
0220     ret = raspberrypi_clock_property(rpi->firmware, data,
0221                      RPI_FIRMWARE_SET_CLOCK_RATE, &_rate);
0222     if (ret)
0223         dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d\n",
0224                     clk_hw_get_name(hw), ret);
0225 
0226     return ret;
0227 }
0228 
0229 static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw,
0230                           struct clk_rate_request *req)
0231 {
0232     struct raspberrypi_clk_data *data =
0233         container_of(hw, struct raspberrypi_clk_data, hw);
0234     struct raspberrypi_clk_variant *variant = data->variant;
0235 
0236     /*
0237      * The firmware will do the rounding but that isn't part of
0238      * the interface with the firmware, so we just do our best
0239      * here.
0240      */
0241 
0242     req->rate = clamp(req->rate, req->min_rate, req->max_rate);
0243 
0244     /*
0245      * We want to aggressively reduce the clock rate here, so let's
0246      * just ignore the requested rate and return the bare minimum
0247      * rate we can get away with.
0248      */
0249     if (variant->minimize && req->min_rate > 0)
0250         req->rate = req->min_rate;
0251 
0252     return 0;
0253 }
0254 
0255 static const struct clk_ops raspberrypi_firmware_clk_ops = {
0256     .is_prepared    = raspberrypi_fw_is_prepared,
0257     .recalc_rate    = raspberrypi_fw_get_rate,
0258     .determine_rate = raspberrypi_fw_dumb_determine_rate,
0259     .set_rate   = raspberrypi_fw_set_rate,
0260 };
0261 
0262 static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
0263                            unsigned int parent,
0264                            unsigned int id,
0265                            struct raspberrypi_clk_variant *variant)
0266 {
0267     struct raspberrypi_clk_data *data;
0268     struct clk_init_data init = {};
0269     u32 min_rate, max_rate;
0270     int ret;
0271 
0272     data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL);
0273     if (!data)
0274         return ERR_PTR(-ENOMEM);
0275     data->rpi = rpi;
0276     data->id = id;
0277     data->variant = variant;
0278 
0279     init.name = devm_kasprintf(rpi->dev, GFP_KERNEL,
0280                    "fw-clk-%s",
0281                    rpi_firmware_clk_names[id]);
0282     init.ops = &raspberrypi_firmware_clk_ops;
0283     init.flags = CLK_GET_RATE_NOCACHE;
0284 
0285     data->hw.init = &init;
0286 
0287     ret = raspberrypi_clock_property(rpi->firmware, data,
0288                      RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
0289                      &min_rate);
0290     if (ret) {
0291         dev_err(rpi->dev, "Failed to get clock %d min freq: %d\n",
0292             id, ret);
0293         return ERR_PTR(ret);
0294     }
0295 
0296     ret = raspberrypi_clock_property(rpi->firmware, data,
0297                      RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
0298                      &max_rate);
0299     if (ret) {
0300         dev_err(rpi->dev, "Failed to get clock %d max freq: %d\n",
0301             id, ret);
0302         return ERR_PTR(ret);
0303     }
0304 
0305     ret = devm_clk_hw_register(rpi->dev, &data->hw);
0306     if (ret)
0307         return ERR_PTR(ret);
0308 
0309     clk_hw_set_rate_range(&data->hw, min_rate, max_rate);
0310 
0311     if (variant->clkdev) {
0312         ret = devm_clk_hw_register_clkdev(rpi->dev, &data->hw,
0313                           NULL, variant->clkdev);
0314         if (ret) {
0315             dev_err(rpi->dev, "Failed to initialize clkdev\n");
0316             return ERR_PTR(ret);
0317         }
0318     }
0319 
0320     if (variant->min_rate) {
0321         unsigned long rate;
0322 
0323         clk_hw_set_rate_range(&data->hw, variant->min_rate, max_rate);
0324 
0325         rate = raspberrypi_fw_get_rate(&data->hw, 0);
0326         if (rate < variant->min_rate) {
0327             ret = raspberrypi_fw_set_rate(&data->hw, variant->min_rate, 0);
0328             if (ret)
0329                 return ERR_PTR(ret);
0330         }
0331     }
0332 
0333     return &data->hw;
0334 }
0335 
0336 struct rpi_firmware_get_clocks_response {
0337     u32 parent;
0338     u32 id;
0339 };
0340 
0341 static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi,
0342                        struct clk_hw_onecell_data *data)
0343 {
0344     struct rpi_firmware_get_clocks_response *clks;
0345     int ret;
0346 
0347     /*
0348      * The firmware doesn't guarantee that the last element of
0349      * RPI_FIRMWARE_GET_CLOCKS is zeroed. So allocate an additional
0350      * zero element as sentinel.
0351      */
0352     clks = devm_kcalloc(rpi->dev,
0353                 RPI_FIRMWARE_NUM_CLK_ID + 1, sizeof(*clks),
0354                 GFP_KERNEL);
0355     if (!clks)
0356         return -ENOMEM;
0357 
0358     ret = rpi_firmware_property(rpi->firmware, RPI_FIRMWARE_GET_CLOCKS,
0359                     clks,
0360                     sizeof(*clks) * RPI_FIRMWARE_NUM_CLK_ID);
0361     if (ret)
0362         return ret;
0363 
0364     while (clks->id) {
0365         struct raspberrypi_clk_variant *variant;
0366 
0367         if (clks->id > RPI_FIRMWARE_NUM_CLK_ID) {
0368             dev_err(rpi->dev, "Unknown clock id: %u (max: %u)\n",
0369                        clks->id, RPI_FIRMWARE_NUM_CLK_ID);
0370             return -EINVAL;
0371         }
0372 
0373         variant = &raspberrypi_clk_variants[clks->id];
0374         if (variant->export) {
0375             struct clk_hw *hw;
0376 
0377             hw = raspberrypi_clk_register(rpi, clks->parent,
0378                               clks->id, variant);
0379             if (IS_ERR(hw))
0380                 return PTR_ERR(hw);
0381 
0382             data->hws[clks->id] = hw;
0383             data->num = clks->id + 1;
0384         }
0385 
0386         clks++;
0387     }
0388 
0389     return 0;
0390 }
0391 
0392 static int raspberrypi_clk_probe(struct platform_device *pdev)
0393 {
0394     struct clk_hw_onecell_data *clk_data;
0395     struct device_node *firmware_node;
0396     struct device *dev = &pdev->dev;
0397     struct rpi_firmware *firmware;
0398     struct raspberrypi_clk *rpi;
0399     int ret;
0400 
0401     /*
0402      * We can be probed either through the an old-fashioned
0403      * platform device registration or through a DT node that is a
0404      * child of the firmware node. Handle both cases.
0405      */
0406     if (dev->of_node)
0407         firmware_node = of_get_parent(dev->of_node);
0408     else
0409         firmware_node = of_find_compatible_node(NULL, NULL,
0410                             "raspberrypi,bcm2835-firmware");
0411     if (!firmware_node) {
0412         dev_err(dev, "Missing firmware node\n");
0413         return -ENOENT;
0414     }
0415 
0416     firmware = devm_rpi_firmware_get(&pdev->dev, firmware_node);
0417     of_node_put(firmware_node);
0418     if (!firmware)
0419         return -EPROBE_DEFER;
0420 
0421     rpi = devm_kzalloc(dev, sizeof(*rpi), GFP_KERNEL);
0422     if (!rpi)
0423         return -ENOMEM;
0424 
0425     rpi->dev = dev;
0426     rpi->firmware = firmware;
0427     platform_set_drvdata(pdev, rpi);
0428 
0429     clk_data = devm_kzalloc(dev, struct_size(clk_data, hws,
0430                          RPI_FIRMWARE_NUM_CLK_ID),
0431                 GFP_KERNEL);
0432     if (!clk_data)
0433         return -ENOMEM;
0434 
0435     ret = raspberrypi_discover_clocks(rpi, clk_data);
0436     if (ret)
0437         return ret;
0438 
0439     ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
0440                       clk_data);
0441     if (ret)
0442         return ret;
0443 
0444     rpi->cpufreq = platform_device_register_data(dev, "raspberrypi-cpufreq",
0445                              -1, NULL, 0);
0446 
0447     return 0;
0448 }
0449 
0450 static int raspberrypi_clk_remove(struct platform_device *pdev)
0451 {
0452     struct raspberrypi_clk *rpi = platform_get_drvdata(pdev);
0453 
0454     platform_device_unregister(rpi->cpufreq);
0455 
0456     return 0;
0457 }
0458 
0459 static const struct of_device_id raspberrypi_clk_match[] = {
0460     { .compatible = "raspberrypi,firmware-clocks" },
0461     { },
0462 };
0463 MODULE_DEVICE_TABLE(of, raspberrypi_clk_match);
0464 
0465 static struct platform_driver raspberrypi_clk_driver = {
0466     .driver = {
0467         .name = "raspberrypi-clk",
0468         .of_match_table = raspberrypi_clk_match,
0469     },
0470     .probe          = raspberrypi_clk_probe,
0471     .remove     = raspberrypi_clk_remove,
0472 };
0473 module_platform_driver(raspberrypi_clk_driver);
0474 
0475 MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>");
0476 MODULE_DESCRIPTION("Raspberry Pi firmware clock driver");
0477 MODULE_LICENSE("GPL");
0478 MODULE_ALIAS("platform:raspberrypi-clk");