summaryrefslogtreecommitdiffstats
path: root/bcm283x-vc4-fixes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'bcm283x-vc4-fixes.patch')
-rw-r--r--bcm283x-vc4-fixes.patch639
1 files changed, 0 insertions, 639 deletions
diff --git a/bcm283x-vc4-fixes.patch b/bcm283x-vc4-fixes.patch
index 3f77b7485..d42ceb62a 100644
--- a/bcm283x-vc4-fixes.patch
+++ b/bcm283x-vc4-fixes.patch
@@ -1,642 +1,3 @@
-From 9db79f3a51c97e0cfcde1b25299e8db9ee3d64ab Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 14 Sep 2016 19:21:29 +0100
-Subject: [PATCH 1/4] drm/vc4: Fall back to using an EDID probe in the absence
- of a GPIO.
-
-On Pi0/1/2, we use an external GPIO line for hotplug detection, since
-the HDMI_HOTPLUG register isn't connected to anything. However, with
-the Pi3 the HPD GPIO line has moved off to a GPIO expander that will
-be tricky to get to (the firmware is constantly polling the expander
-using i2c0, so we'll need to coordinate with it).
-
-As a stop-gap, if we don't have a GPIO line, use an EDID probe to
-detect connection. Fixes HDMI display on the pi3.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_hdmi.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
-index 4452f36..5adc0c7 100644
---- a/drivers/gpu/drm/vc4/vc4_hdmi.c
-+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
-@@ -174,6 +174,9 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
- return connector_status_disconnected;
- }
-
-+ if (drm_probe_ddc(vc4->hdmi->ddc))
-+ return connector_status_connected;
-+
- if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
- return connector_status_connected;
- else
---
-2.9.3
-
-From 7b4c39f34fbbdfe0cd0e626686ee01ab96601598 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 16 Sep 2016 10:59:45 +0100
-Subject: [PATCH 2/4] drm/vc4: Enable limited range RGB output on HDMI with CEA
- modes.
-
-Fixes broken grayscale ramps on many HDMI monitors, where large areas
-at the ends of the ramp would all appear as black or white.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_hdmi.c | 31 +++++++++++++++++++++++++++++--
- drivers/gpu/drm/vc4/vc4_regs.h | 9 ++++++++-
- 2 files changed, 37 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
-index 5adc0c7..5df4e74 100644
---- a/drivers/gpu/drm/vc4/vc4_hdmi.c
-+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
-@@ -276,6 +276,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *unadjusted_mode,
- struct drm_display_mode *mode)
- {
-+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
- struct drm_device *dev = encoder->dev;
- struct vc4_dev *vc4 = to_vc4_dev(dev);
- bool debug_dump_regs = false;
-@@ -291,6 +292,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
- u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
- VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
- VC4_HDMI_VERTB_VBP));
-+ u32 csc_ctl;
-
- if (debug_dump_regs) {
- DRM_INFO("HDMI regs before:\n");
-@@ -329,9 +331,34 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
- (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
- (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
-
-+ csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
-+ VC4_HD_CSC_CTL_ORDER);
-+
-+ if (vc4_encoder->hdmi_monitor && drm_match_cea_mode(mode) > 1) {
-+ /* CEA VICs other than #1 requre limited range RGB
-+ * output. Apply a colorspace conversion to squash
-+ * 0-255 down to 16-235. The matrix here is:
-+ *
-+ * [ 0 0 0.8594 16]
-+ * [ 0 0.8594 0 16]
-+ * [ 0.8594 0 0 16]
-+ * [ 0 0 0 1]
-+ */
-+ csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
-+ csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
-+ csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
-+ VC4_HD_CSC_CTL_MODE);
-+
-+ HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000);
-+ HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0);
-+ HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000);
-+ HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
-+ HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
-+ HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
-+ }
-+
- /* The RGB order applies even when CSC is disabled. */
-- HD_WRITE(VC4_HD_CSC_CTL, VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
-- VC4_HD_CSC_CTL_ORDER));
-+ HD_WRITE(VC4_HD_CSC_CTL, csc_ctl);
-
- HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
-
-diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
-index 160942a..9ecd6ff 100644
---- a/drivers/gpu/drm/vc4/vc4_regs.h
-+++ b/drivers/gpu/drm/vc4/vc4_regs.h
-@@ -528,10 +528,17 @@
- # define VC4_HD_CSC_CTL_MODE_SHIFT 2
- # define VC4_HD_CSC_CTL_MODE_RGB_TO_SD_YPRPB 0
- # define VC4_HD_CSC_CTL_MODE_RGB_TO_HD_YPRPB 1
--# define VC4_HD_CSC_CTL_MODE_CUSTOM 2
-+# define VC4_HD_CSC_CTL_MODE_CUSTOM 3
- # define VC4_HD_CSC_CTL_RGB2YCC BIT(1)
- # define VC4_HD_CSC_CTL_ENABLE BIT(0)
-
-+#define VC4_HD_CSC_12_11 0x044
-+#define VC4_HD_CSC_14_13 0x048
-+#define VC4_HD_CSC_22_21 0x04c
-+#define VC4_HD_CSC_24_23 0x050
-+#define VC4_HD_CSC_32_31 0x054
-+#define VC4_HD_CSC_34_33 0x058
-+
- #define VC4_HD_FRAME_COUNT 0x068
-
- /* HVS display list information. */
---
-2.9.3
-
-From f379f5432e4b74e3d1d894ce2fefbe1b8a3c24fd Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 28 Sep 2016 19:20:44 -0700
-Subject: [PATCH 4/4] drm/vc4: Increase timeout for HDMI_SCHEDULER_CONTROL
- changes.
-
-Fixes occasional debug spew at boot when connected directly through
-HDMI, and probably confusing the HDMI state machine when we go trying
-to poke registers for the enable sequence too soon.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
-index 5df4e74..9a6883d 100644
---- a/drivers/gpu/drm/vc4/vc4_hdmi.c
-+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
-@@ -399,7 +399,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
- VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
-
- ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
-- VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1);
-+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
- WARN_ONCE(ret, "Timeout waiting for "
- "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
- } else {
-@@ -411,7 +411,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
- ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
-
- ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
-- VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1);
-+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
- WARN_ONCE(ret, "Timeout waiting for "
- "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
- }
---
-2.9.3
-
-From bd712d14886c37eb804036b2ac3036df79d33476 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 29 Sep 2016 15:34:43 -0700
-Subject: [PATCH] drm/vc4: Set up the AVI and SPD infoframes.
-
-Fixes a purple bar on the left side of the screen with my Dell
-2408WFP. It will also be required for supporting the double-clocked
-video modes.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_hdmi.c | 136 +++++++++++++++++++++++++++++++++++++++--
- drivers/gpu/drm/vc4/vc4_regs.h | 5 ++
- 2 files changed, 136 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
-index 9a6883d..f722334 100644
---- a/drivers/gpu/drm/vc4/vc4_hdmi.c
-+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
-@@ -62,6 +62,8 @@ struct vc4_hdmi {
- struct vc4_hdmi_encoder {
- struct vc4_encoder base;
- bool hdmi_monitor;
-+ bool limited_rgb_range;
-+ bool rgb_range_selectable;
- };
-
- static inline struct vc4_hdmi_encoder *
-@@ -205,6 +207,12 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
- return -ENODEV;
-
- vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
-+
-+ if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
-+ vc4_encoder->rgb_range_selectable =
-+ drm_rgb_quant_range_selectable(edid);
-+ }
-+
- drm_mode_connector_update_edid_property(connector, edid);
- ret = drm_add_edid_modes(connector, edid);
-
-@@ -272,6 +280,117 @@ static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = {
- .destroy = vc4_hdmi_encoder_destroy,
- };
-
-+static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
-+ enum hdmi_infoframe_type type)
-+{
-+ struct drm_device *dev = encoder->dev;
-+ struct vc4_dev *vc4 = to_vc4_dev(dev);
-+ u32 packet_id = type - 0x80;
-+
-+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
-+ HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
-+
-+ return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
-+ BIT(packet_id)), 100);
-+}
-+
-+static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
-+ union hdmi_infoframe *frame)
-+{
-+ struct drm_device *dev = encoder->dev;
-+ struct vc4_dev *vc4 = to_vc4_dev(dev);
-+ u32 packet_id = frame->any.type - 0x80;
-+ u32 packet_reg = VC4_HDMI_GCP_0 + VC4_HDMI_PACKET_STRIDE * packet_id;
-+ uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
-+ ssize_t len, i;
-+ int ret;
-+
-+ WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
-+ VC4_HDMI_RAM_PACKET_ENABLE),
-+ "Packet RAM has to be on to store the packet.");
-+
-+ len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer));
-+ if (len < 0)
-+ return;
-+
-+ ret = vc4_hdmi_stop_packet(encoder, frame->any.type);
-+ if (ret) {
-+ DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret);
-+ return;
-+ }
-+
-+ for (i = 0; i < len; i += 7) {
-+ HDMI_WRITE(packet_reg,
-+ buffer[i + 0] << 0 |
-+ buffer[i + 1] << 8 |
-+ buffer[i + 2] << 16);
-+ packet_reg += 4;
-+
-+ HDMI_WRITE(packet_reg,
-+ buffer[i + 3] << 0 |
-+ buffer[i + 4] << 8 |
-+ buffer[i + 5] << 16 |
-+ buffer[i + 6] << 24);
-+ packet_reg += 4;
-+ }
-+
-+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
-+ HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
-+ ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
-+ BIT(packet_id)), 100);
-+ if (ret)
-+ DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
-+}
-+
-+static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
-+{
-+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-+ struct drm_crtc *crtc = encoder->crtc;
-+ const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
-+ union hdmi_infoframe frame;
-+ int ret;
-+
-+ ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
-+ if (ret < 0) {
-+ DRM_ERROR("couldn't fill AVI infoframe\n");
-+ return;
-+ }
-+
-+ if (vc4_encoder->rgb_range_selectable) {
-+ if (vc4_encoder->limited_rgb_range) {
-+ frame.avi.quantization_range =
-+ HDMI_QUANTIZATION_RANGE_LIMITED;
-+ } else {
-+ frame.avi.quantization_range =
-+ HDMI_QUANTIZATION_RANGE_FULL;
-+ }
-+ }
-+
-+ vc4_hdmi_write_infoframe(encoder, &frame);
-+}
-+
-+static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
-+{
-+ union hdmi_infoframe frame;
-+ int ret;
-+
-+ ret = hdmi_spd_infoframe_init(&frame.spd, "Broadcom", "Videocore");
-+ if (ret < 0) {
-+ DRM_ERROR("couldn't fill SPD infoframe\n");
-+ return;
-+ }
-+
-+ frame.spd.sdi = HDMI_SPD_SDI_PC;
-+
-+ vc4_hdmi_write_infoframe(encoder, &frame);
-+}
-+
-+static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
-+{
-+ vc4_hdmi_set_avi_infoframe(encoder);
-+ vc4_hdmi_set_spd_infoframe(encoder);
-+}
-+
- static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *unadjusted_mode,
- struct drm_display_mode *mode)
-@@ -336,8 +455,9 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
-
- if (vc4_encoder->hdmi_monitor && drm_match_cea_mode(mode) > 1) {
- /* CEA VICs other than #1 requre limited range RGB
-- * output. Apply a colorspace conversion to squash
-- * 0-255 down to 16-235. The matrix here is:
-+ * output unless overridden by an AVI infoframe.
-+ * Apply a colorspace conversion to squash 0-255 down
-+ * to 16-235. The matrix here is:
- *
- * [ 0 0 0.8594 16]
- * [ 0 0.8594 0 16]
-@@ -355,6 +475,9 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
- HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
- HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
- HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
-+ vc4_encoder->limited_rgb_range = true;
-+ } else {
-+ vc4_encoder->limited_rgb_range = false;
- }
-
- /* The RGB order applies even when CSC is disabled. */
-@@ -373,6 +496,8 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
- struct drm_device *dev = encoder->dev;
- struct vc4_dev *vc4 = to_vc4_dev(dev);
-
-+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
-+
- HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
- HD_WRITE(VC4_HD_VID_CTL,
- HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
-@@ -425,9 +550,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
- HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
- VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
-
-- /* XXX: Set HDMI_RAM_PACKET_CONFIG (1 << 16) and set
-- * up the infoframe.
-- */
-+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
-+ VC4_HDMI_RAM_PACKET_ENABLE);
-+
-+ vc4_hdmi_set_infoframes(encoder);
-
- drift = HDMI_READ(VC4_HDMI_FIFO_CTL);
- drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
-diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
-index 9ecd6ff..a4b5370 100644
---- a/drivers/gpu/drm/vc4/vc4_regs.h
-+++ b/drivers/gpu/drm/vc4/vc4_regs.h
-@@ -438,6 +438,8 @@
- #define VC4_HDMI_RAM_PACKET_CONFIG 0x0a0
- # define VC4_HDMI_RAM_PACKET_ENABLE BIT(16)
-
-+#define VC4_HDMI_RAM_PACKET_STATUS 0x0a4
-+
- #define VC4_HDMI_HORZA 0x0c4
- # define VC4_HDMI_HORZA_VPOS BIT(14)
- # define VC4_HDMI_HORZA_HPOS BIT(13)
-@@ -499,6 +501,9 @@
-
- #define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0
-
-+#define VC4_HDMI_GCP_0 0x400
-+#define VC4_HDMI_PACKET_STRIDE 0x24
-+
- #define VC4_HD_M_CTL 0x00c
- # define VC4_HD_M_REGISTER_FILE_STANDBY (3 << 6)
- # define VC4_HD_M_RAM_STANDBY (3 << 4)
---
-2.9.3
-
-From c4e634ce412d97f0e61223b2a5b3f8f9600cd4dc Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 30 Sep 2016 10:07:27 -0700
-Subject: clk: bcm2835: Clamp the PLL's requested rate to the hardware limits.
-
-Fixes setting low-resolution video modes on HDMI. Now the PLLH_PIX
-divider adjusts itself until the PLLH is within bounds.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
----
- drivers/clk/bcm/clk-bcm2835.c | 11 ++++-------
- 1 file changed, 4 insertions(+), 7 deletions(-)
-
-diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
-index b68bf57..8c7763f 100644
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -502,8 +502,12 @@ static long bcm2835_pll_rate_from_divisors(unsigned long parent_rate,
- static long bcm2835_pll_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
- {
-+ struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
-+ const struct bcm2835_pll_data *data = pll->data;
- u32 ndiv, fdiv;
-
-+ rate = clamp(rate, data->min_rate, data->max_rate);
-+
- bcm2835_pll_choose_ndiv_and_fdiv(rate, *parent_rate, &ndiv, &fdiv);
-
- return bcm2835_pll_rate_from_divisors(*parent_rate, ndiv, fdiv, 1);
-@@ -608,13 +612,6 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw,
- u32 ana[4];
- int i;
-
-- if (rate < data->min_rate || rate > data->max_rate) {
-- dev_err(cprman->dev, "%s: rate out of spec: %lu vs (%lu, %lu)\n",
-- clk_hw_get_name(hw), rate,
-- data->min_rate, data->max_rate);
-- return -EINVAL;
-- }
--
- if (rate > data->max_fb_rate) {
- use_fb_prediv = true;
- rate /= 2;
---
-cgit v0.12
-
-From e69fdcca836f0b81a2260b69429c8622a80ea891 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 1 Jun 2016 12:05:33 -0700
-Subject: clk: bcm2835: Mark the VPU clock as critical
-
-The VPU clock is also the clock for our AXI bus, so we really can't
-disable it. This might have happened during boot if, for example,
-uart1 (aux_uart clock) probed and was then disabled before the other
-consumers of the VPU clock had probed.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Acked-by: Martin Sperl <kernel@martin.sperl.org>
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
----
- drivers/clk/bcm/clk-bcm2835.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
-index 7a79708..d9db03c 100644
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -443,6 +443,8 @@ struct bcm2835_clock_data {
- /* Number of fractional bits in the divider */
- u32 frac_bits;
-
-+ u32 flags;
-+
- bool is_vpu_clock;
- bool is_mash_clock;
- };
-@@ -1230,7 +1232,7 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
- init.parent_names = parents;
- init.num_parents = data->num_mux_parents;
- init.name = data->name;
-- init.flags = CLK_IGNORE_UNUSED;
-+ init.flags = data->flags | CLK_IGNORE_UNUSED;
-
- if (data->is_vpu_clock) {
- init.ops = &bcm2835_vpu_clock_clk_ops;
-@@ -1649,6 +1651,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
- .div_reg = CM_VPUDIV,
- .int_bits = 12,
- .frac_bits = 8,
-+ .flags = CLK_IS_CRITICAL,
- .is_vpu_clock = true),
-
- /* clocks with per parent mux */
---
-cgit v0.12
-
-From eddcbe8398fc7103fccd22aa6df6917caf0123bf Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 1 Jun 2016 12:05:34 -0700
-Subject: clk: bcm2835: Mark GPIO clocks enabled at boot as critical
-
-These divide off of PLLD_PER and are used for the ethernet and wifi
-PHYs source PLLs. Neither of them is currently represented by a phy
-device that would grab the clock for us.
-
-This keeps other drivers from killing the networking PHYs when they
-disable their own clocks and trigger PLLD_PER's refcount going to 0.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Acked-by: Martin Sperl <kernel@martin.sperl.org>
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
----
- drivers/clk/bcm/clk-bcm2835.c | 10 +++++++++-
- 1 file changed, 9 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
-index d9db03c..400615b 100644
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -1239,6 +1239,12 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
- } else {
- init.ops = &bcm2835_clock_clk_ops;
- init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
-+
-+ /* If the clock wasn't actually enabled at boot, it's not
-+ * critical.
-+ */
-+ if (!(cprman_read(cprman, data->ctl_reg) & CM_ENABLE))
-+ init.flags &= ~CLK_IS_CRITICAL;
- }
-
- clock = devm_kzalloc(cprman->dev, sizeof(*clock), GFP_KERNEL);
-@@ -1708,13 +1714,15 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
- .div_reg = CM_GP1DIV,
- .int_bits = 12,
- .frac_bits = 12,
-+ .flags = CLK_IS_CRITICAL,
- .is_mash_clock = true),
- [BCM2835_CLOCK_GP2] = REGISTER_PER_CLK(
- .name = "gp2",
- .ctl_reg = CM_GP2CTL,
- .div_reg = CM_GP2DIV,
- .int_bits = 12,
-- .frac_bits = 12),
-+ .frac_bits = 12,
-+ .flags = CLK_IS_CRITICAL),
-
- /* HDMI state machine */
- [BCM2835_CLOCK_HSM] = REGISTER_PER_CLK(
---
-cgit v0.12
-
-From 9e400c5cc5c105e35216ac59a346f20cdd7613be Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 1 Jun 2016 12:05:35 -0700
-Subject: clk: bcm2835: Mark the CM SDRAM clock's parent as critical
-
-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 turns
-on the CM SDRAM clock (using its pre-initialized parent) and switches
-SDRAM to using the CM clock to do PVT recalibration.
-
-This avoids system hangs if we choose SDRAM's parent for some other
-clock, then disable that clock.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Acked-by: Martin Sperl <kernel@martin.sperl.org>
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
----
- drivers/clk/bcm/clk-bcm2835.c | 25 +++++++++++++++++++++++++
- 1 file changed, 25 insertions(+)
-
-diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
-index 400615b..c6420b3 100644
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -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>
-@@ -1801,6 +1802,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;
-@@ -1810,6 +1830,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),
-@@ -1840,6 +1861,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);
- }
---
-cgit v0.12
-
From 30772942cc1095c3129eecfa182e2c568e566b9d Mon Sep 17 00:00:00 2001
From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Thu, 13 Oct 2016 11:54:31 +0300