Skip to content

Rpi 4.4.y dsi stub squash #1556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Aug 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,17 @@ Required properties:
- #clock-cells: Should be <1>. The permitted clock-specifier values can be
found in include/dt-bindings/clock/bcm2835.h
- reg: Specifies base physical address and size of the registers
- clocks: The external oscillator clock phandle
- clocks: phandles to the parent clocks used as input to the module, in
the following order:

- External oscillator
- DSI1 byte clock
- DSI1 DDR2 clock
- DSI1 DDR clock

Only external oscillator is required. The DSI clocks may
not be present, in which case their children will be
unusable.

Example:

Expand Down
24 changes: 22 additions & 2 deletions arch/arm/boot/dts/bcm2708_common.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <dt-bindings/clock/bcm2835-aux.h>
#include "dt-bindings/power/raspberrypi-power.h"
#include "dt-bindings/gpio/gpio.h"
#include "dt-bindings/pinctrl/bcm2835.h"
#include "skeleton.dtsi"

/ {
Expand Down Expand Up @@ -110,9 +111,10 @@
reg = <0x7e101000 0x2000>;

/* CPRMAN derives everything from the platform's
* oscillator.
* oscillator except for a few clocks that may
* derive from something else derived from CPRMAN..
*/
clocks = <&clk_osc>;
clocks = <&clk_osc>, <&dsi1 0>, <&dsi1 1>, <&dsi1 2>;
status = "disabled";
};

Expand Down Expand Up @@ -282,6 +284,24 @@
status = "disabled";
};

dsi1: dsi@7e700000 {
#address-cells = <1>;
#size-cells = <0>;
#clock-cells = <1>;

compatible = "brcm,bcm2835-dsi1";
reg = <0x7e700000 0x8c>;
interrupts = <2 12>;

clocks = <&cprman BCM2835_PLLD_DSI1>,
<&cprman BCM2835_CLOCK_DSI1E>,
<&cprman BCM2835_CLOCK_DSI1P>;
clock-names = "phy", "escape", "pixel";
clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr";
status = "disabled";
power-domains = <&power RPI_POWER_DOMAIN_DSI1>;
};

i2c1: i2c@7e804000 {
compatible = "brcm,bcm2708-i2c";
reg = <0x7e804000 0x1000>;
Expand Down
16 changes: 16 additions & 0 deletions arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,22 @@
};
};

fragment@16 {
target = <&dsi1>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";

brcm,panel = <&pitouchscreen>;

pitouchscreen: panel {
compatible = "raspberrypi,touchscreen";
reg = <0>;
};
};
};

__overrides__ {
cma-256 = <0>,"+0-1-2-3-4";
cma-192 = <0>,"-0+1-2-3-4";
Expand Down
1 change: 1 addition & 0 deletions arch/arm/configs/bcm2709_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,7 @@ CONFIG_DRM=m
CONFIG_DRM_LOAD_EDID_FIRMWARE=y
CONFIG_DRM_UDL=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m
CONFIG_DRM_VC4=m
CONFIG_FB=y
CONFIG_FB_BCM2708=y
Expand Down
1 change: 1 addition & 0 deletions arch/arm/configs/bcmrpi_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,7 @@ CONFIG_DRM=m
CONFIG_DRM_LOAD_EDID_FIRMWARE=y
CONFIG_DRM_UDL=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m
CONFIG_DRM_VC4=m
CONFIG_FB=y
CONFIG_FB_BCM2708=y
Expand Down
120 changes: 106 additions & 14 deletions drivers/clk/bcm/clk-bcm2835.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/clk.h>
#include <linux/clk/bcm2835.h>
#include <linux/debugfs.h>
#include <linux/module.h>
Expand Down Expand Up @@ -296,11 +297,29 @@
#define LOCK_TIMEOUT_NS 100000000
#define BCM2835_MAX_FB_RATE 1750000000u

/*
* Names of clocks used within the driver that need to be replaced
* with an external parent's name. This array is in the order that
* the clocks node in the DT references external clocks.
*/
static const char *cprman_parent_names[] = {
"xosc",
"dsi1_byte",
"dsi1_ddr2",
"dsi1_ddr",
};

struct bcm2835_cprman {
struct device *dev;
void __iomem *regs;
spinlock_t regs_lock; /* spinlock for all clocks */
const char *osc_name;

/*
* Real names of cprman clock parents looked up through
* of_clk_get_parent_name(), which will be used in the
* parent_names[] arrays for clock registration.
*/
const char *real_parent_names[ARRAY_SIZE(cprman_parent_names)];

struct clk_onecell_data onecell;
struct clk *clks[];
Expand Down Expand Up @@ -915,6 +934,9 @@ static long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock,
const struct bcm2835_clock_data *data = clock->data;
u64 temp;

if (data->int_bits == 0 && data->frac_bits == 0)
return parent_rate;

/*
* The divisor is a 12.12 fixed point field, but only some of
* the bits are populated in any given clock.
Expand All @@ -938,7 +960,12 @@ static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw,
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
struct bcm2835_cprman *cprman = clock->cprman;
const struct bcm2835_clock_data *data = clock->data;
u32 div = cprman_read(cprman, data->div_reg);
u32 div;

if (data->int_bits == 0 && data->frac_bits == 0)
return parent_rate;

div = cprman_read(cprman, data->div_reg);

return bcm2835_clock_rate_from_divisor(clock, parent_rate, div);
}
Expand Down Expand Up @@ -1167,7 +1194,7 @@ static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman,
memset(&init, 0, sizeof(init));

/* All of the PLLs derive from the external oscillator. */
init.parent_names = &cprman->osc_name;
init.parent_names = &cprman->real_parent_names[0];
init.num_parents = 1;
init.name = data->name;
init.ops = &bcm2835_pll_clk_ops;
Expand Down Expand Up @@ -1208,7 +1235,7 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
init.num_parents = 1;
init.name = divider_name;
init.ops = &bcm2835_pll_divider_clk_ops;
init.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED;
init.flags = CLK_IGNORE_UNUSED;

divider = devm_kzalloc(cprman->dev, sizeof(*divider), GFP_KERNEL);
if (!divider)
Expand Down Expand Up @@ -1250,17 +1277,21 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
struct bcm2835_clock *clock;
struct clk_init_data init;
const char *parents[1 << CM_SRC_BITS];
size_t i;
size_t i, j;

/*
* Replace our "xosc" references with the oscillator's
* actual name.
* Replace our strings referencing parent clocks with the
* actual clock-output-name of the parent.
*/
for (i = 0; i < data->num_mux_parents; i++) {
if (strcmp(data->parents[i], "xosc") == 0)
parents[i] = cprman->osc_name;
else
parents[i] = data->parents[i];
parents[i] = data->parents[i];

for (j = 0; j < ARRAY_SIZE(cprman_parent_names); j++) {
if (strcmp(parents[i], cprman_parent_names[j]) == 0) {
parents[i] = cprman->real_parent_names[j];
break;
}
}
}

memset(&init, 0, sizeof(init));
Expand Down Expand Up @@ -1379,6 +1410,28 @@ static const char *const bcm2835_clock_vpu_parents[] = {
.parents = bcm2835_clock_vpu_parents, \
__VA_ARGS__)

/*
* DSI1 parent clocks. The DSI1 byte clock comes from the DSI1 PHY,
* which in turn sources from plld_dsi1.
*/
static const char *const bcm2835_clock_dsi1_parents[] = {
"gnd",
"xosc",
"testdebug0",
"testdebug1",
"dsi1_ddr",
"dsi1_ddr_inv",
"dsi1_ddr2",
"dsi1_ddr2_inv",
"dsi1_byte",
"dsi1_byte_inv",
};

#define REGISTER_DSI1_CLK(...) REGISTER_CLK( \
.num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi1_parents), \
.parents = bcm2835_clock_dsi1_parents, \
__VA_ARGS__)

/*
* the real definition of all the pll, pll_dividers and clocks
* these make use of the above REGISTER_* macros
Expand Down Expand Up @@ -1824,7 +1877,12 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.div_reg = CM_DSI1EDIV,
.int_bits = 4,
.frac_bits = 8),

[BCM2835_CLOCK_DSI1P] = REGISTER_DSI1_CLK(
.name = "dsi1p",
.ctl_reg = CM_DSI1PCTL,
.div_reg = CM_DSI1PDIV,
.int_bits = 0,
.frac_bits = 0),
/* the gates */

/*
Expand All @@ -1839,6 +1897,25 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.ctl_reg = CM_PERIICTL),
};

/*
* Permanently take a reference on the parent of the SDRAM clock.
*
* While the SDRAM is being driven by its dedicated PLL most of the
* time, there is a little loop running in the firmware that
* periodically switches the SDRAM to using our CM clock to do PVT
* recalibration, with the assumption that the previously configured
* SDRAM parent is still enabled and running.
*/
static int bcm2835_mark_sdc_parent_critical(struct clk *sdc)
{
struct clk *parent = clk_get_parent(sdc);

if (IS_ERR(parent))
return PTR_ERR(parent);

return clk_prepare_enable(parent);
}

static int bcm2835_clk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
Expand All @@ -1848,6 +1925,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
const struct bcm2835_clk_desc *desc;
const size_t asize = ARRAY_SIZE(clk_desc_array);
size_t i;
int ret;

cprman = devm_kzalloc(dev,
sizeof(*cprman) + asize * sizeof(*clks),
Expand All @@ -1862,8 +1940,18 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
if (IS_ERR(cprman->regs))
return PTR_ERR(cprman->regs);

cprman->osc_name = of_clk_get_parent_name(dev->of_node, 0);
if (!cprman->osc_name)
for (i = 0; i < ARRAY_SIZE(cprman_parent_names); i++) {
cprman->real_parent_names[i] =
of_clk_get_parent_name(dev->of_node, i);
}
/*
* Make sure the external oscillator has been registered.
*
* The other (DSI) clocks are not present on older device
* trees, which we still need to support for backwards
* compatibility.
*/
if (!cprman->real_parent_names[0])
return -ENODEV;

platform_set_drvdata(pdev, cprman);
Expand All @@ -1878,6 +1966,10 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
clks[i] = desc->clk_register(cprman, desc->data);
}

ret = bcm2835_mark_sdc_parent_critical(clks[BCM2835_CLOCK_SDRAM]);
if (ret)
return ret;

return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
&cprman->onecell);
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ menuconfig DRM
(/dev/agpgart) support if it is available for your platform.

config DRM_MIPI_DSI
bool
tristate
depends on DRM

config DRM_KMS_HELPER
Expand Down
3 changes: 0 additions & 3 deletions drivers/gpu/drm/drm_fb_cma_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,9 +348,6 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,

}

/* disable all the possible outputs/crtcs before entering KMS mode */
drm_helper_disable_unused_functions(dev);

ret = drm_fb_helper_initial_config(helper, preferred_bpp);
if (ret < 0) {
dev_err(dev->dev, "Failed to set initial hw configuration.\n");
Expand Down
25 changes: 25 additions & 0 deletions drivers/gpu/drm/drm_mipi_dsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,24 @@ static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
return of_driver_match_device(dev, drv);
}

/**
* Send modalias events when devices are created on the bus, so that
* modules can load automatically.
*/
static int mipi_dsi_uevent(struct device *dev, struct kobj_uevent_env *env)
{
int rc;

/* Just do the OF uevent, which emits the compatible string so
* that a MODULE_DEVICE_TABLE(of, ...) works.
*/
rc = of_device_uevent_modalias(dev, env);
if (rc != -ENODEV)
return rc;

return 0;
}

static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
.runtime_suspend = pm_generic_runtime_suspend,
.runtime_resume = pm_generic_runtime_resume,
Expand All @@ -65,6 +83,7 @@ static struct bus_type mipi_dsi_bus_type = {
.name = "mipi-dsi",
.match = mipi_dsi_device_match,
.pm = &mipi_dsi_device_pm_ops,
.uevent = mipi_dsi_uevent,
};

static int of_device_match(struct device *dev, void *data)
Expand Down Expand Up @@ -928,6 +947,12 @@ static int __init mipi_dsi_bus_init(void)
}
postcore_initcall(mipi_dsi_bus_init);

static void __exit mipi_dsi_bus_exit(void)
{
bus_unregister(&mipi_dsi_bus_type);
}
module_exit(mipi_dsi_bus_exit);

MODULE_AUTHOR("Andrzej Hajda <[email protected]>");
MODULE_DESCRIPTION("MIPI DSI Bus");
MODULE_LICENSE("GPL and additional rights");
1 change: 1 addition & 0 deletions drivers/gpu/drm/imx/imx-drm-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
dev_warn(drm->dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n");
legacyfb_depth = 16;
}
drm_helper_disable_unused_functions(drm);
imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth,
drm->mode_config.num_crtc, MAX_CRTC);
if (IS_ERR(imxdrm->fbhelper)) {
Expand Down
Loading