mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-03-09 15:40:20 +00:00
Update to lastest kernel versions
This commit is contained in:
parent
dfd30fd2b8
commit
f1e3dc3f73
37 changed files with 767 additions and 2695 deletions
|
@ -76,6 +76,7 @@ CONFIG_ARM64_4K_PAGES=y
|
|||
CONFIG_ARM64_CONT_SHIFT=4
|
||||
# CONFIG_ARM64_CRYPTO is not set
|
||||
CONFIG_ARM64_ERRATUM_1024718=y
|
||||
CONFIG_ARM64_ERRATUM_1463225=y
|
||||
CONFIG_ARM64_ERRATUM_819472=y
|
||||
CONFIG_ARM64_ERRATUM_824069=y
|
||||
CONFIG_ARM64_ERRATUM_826319=y
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
From f41f870c3cf38e766961131e3a79bcb7845a8d55 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
Date: Fri, 10 May 2019 14:11:58 +0100
|
||||
Subject: [PATCH 523/528] staging: bcm2835-codec: Convert V4L2 nsec timestamps
|
||||
to MMAL usec
|
||||
|
||||
V4L2 uses nsecs, whilst MMAL uses usecs, but the code wasn't converting
|
||||
between them. This upsets video encode rate control.
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
---
|
||||
.../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
index 22588f78287e..5c7fc39cd921 100644
|
||||
--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
@@ -823,7 +823,8 @@ static void op_buffer_cb(struct vchiq_mmal_instance *instance,
|
||||
vb2->flags |= V4L2_BUF_FLAG_LAST;
|
||||
}
|
||||
|
||||
- vb2->vb2_buf.timestamp = mmal_buf->pts;
|
||||
+ /* vb2 timestamps in nsecs, mmal in usecs */
|
||||
+ vb2->vb2_buf.timestamp = mmal_buf->pts * 1000;
|
||||
|
||||
vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
|
||||
if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
|
||||
@@ -847,6 +848,7 @@ static void op_buffer_cb(struct vchiq_mmal_instance *instance,
|
||||
static void vb2_to_mmal_buffer(struct m2m_mmal_buffer *buf,
|
||||
struct vb2_v4l2_buffer *vb2)
|
||||
{
|
||||
+ u64 pts;
|
||||
buf->mmal.mmal_flags = 0;
|
||||
if (vb2->flags & V4L2_BUF_FLAG_KEYFRAME)
|
||||
buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
|
||||
@@ -869,7 +871,10 @@ static void vb2_to_mmal_buffer(struct m2m_mmal_buffer *buf,
|
||||
if (!buf->mmal.length || vb2->flags & V4L2_BUF_FLAG_LAST)
|
||||
buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
|
||||
|
||||
- buf->mmal.pts = vb2->vb2_buf.timestamp;
|
||||
+ /* vb2 timestamps in nsecs, mmal in usecs */
|
||||
+ pts = vb2->vb2_buf.timestamp;
|
||||
+ do_div(pts, 1000);
|
||||
+ buf->mmal.pts = pts;
|
||||
buf->mmal.dts = MMAL_TIME_UNKNOWN;
|
||||
}
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
From 16a9ad722bd6dce2e90db11b3cc4d8306d698706 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
Date: Fri, 10 May 2019 14:13:11 +0100
|
||||
Subject: [PATCH 524/528] staging: bcm2835-codec: Add support for setting
|
||||
S_PARM and G_PARM
|
||||
|
||||
Video encode can use the frame rate for rate control calculations,
|
||||
therefore plumb it through from V4L2's [S|G]_PARM ioctl.
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
---
|
||||
.../bcm2835-codec/bcm2835-v4l2-codec.c | 52 +++++++++++++++++--
|
||||
1 file changed, 48 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
index 5c7fc39cd921..708f76b7aa92 100644
|
||||
--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
@@ -447,6 +447,8 @@ struct bcm2835_codec_ctx {
|
||||
/* Source and destination queue data */
|
||||
struct bcm2835_codec_q_data q_data[2];
|
||||
s32 bitrate;
|
||||
+ unsigned int framerate_num;
|
||||
+ unsigned int framerate_denom;
|
||||
|
||||
bool aborting;
|
||||
int num_ip_buffers;
|
||||
@@ -610,8 +612,8 @@ static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
|
||||
port->es.video.height = q_data->height;
|
||||
port->es.video.crop.width = q_data->crop_width;
|
||||
port->es.video.crop.height = q_data->crop_height;
|
||||
- port->es.video.frame_rate.num = 0;
|
||||
- port->es.video.frame_rate.den = 1;
|
||||
+ port->es.video.frame_rate.num = ctx->framerate_num;
|
||||
+ port->es.video.frame_rate.den = ctx->framerate_denom;
|
||||
} else {
|
||||
/* Compressed format - leave resolution as 0 for decode */
|
||||
if (ctx->dev->role == DECODE) {
|
||||
@@ -625,9 +627,9 @@ static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
|
||||
port->es.video.crop.width = q_data->crop_width;
|
||||
port->es.video.crop.height = q_data->crop_height;
|
||||
port->format.bitrate = ctx->bitrate;
|
||||
+ port->es.video.frame_rate.num = ctx->framerate_num;
|
||||
+ port->es.video.frame_rate.den = ctx->framerate_denom;
|
||||
}
|
||||
- port->es.video.frame_rate.num = 0;
|
||||
- port->es.video.frame_rate.den = 1;
|
||||
}
|
||||
port->es.video.crop.x = 0;
|
||||
port->es.video.crop.y = 0;
|
||||
@@ -1361,6 +1363,41 @@ static int vidioc_s_selection(struct file *file, void *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int vidioc_s_parm(struct file *file, void *priv,
|
||||
+ struct v4l2_streamparm *parm)
|
||||
+{
|
||||
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
|
||||
+
|
||||
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ctx->framerate_num =
|
||||
+ parm->parm.output.timeperframe.denominator;
|
||||
+ ctx->framerate_denom =
|
||||
+ parm->parm.output.timeperframe.numerator;
|
||||
+
|
||||
+ parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vidioc_g_parm(struct file *file, void *priv,
|
||||
+ struct v4l2_streamparm *parm)
|
||||
+{
|
||||
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
|
||||
+
|
||||
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
|
||||
+ parm->parm.output.timeperframe.denominator =
|
||||
+ ctx->framerate_num;
|
||||
+ parm->parm.output.timeperframe.numerator =
|
||||
+ ctx->framerate_denom;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int vidioc_subscribe_evt(struct v4l2_fh *fh,
|
||||
const struct v4l2_event_subscription *sub)
|
||||
{
|
||||
@@ -1725,6 +1762,9 @@ static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
|
||||
.vidioc_g_selection = vidioc_g_selection,
|
||||
.vidioc_s_selection = vidioc_s_selection,
|
||||
|
||||
+ .vidioc_g_parm = vidioc_g_parm,
|
||||
+ .vidioc_s_parm = vidioc_s_parm,
|
||||
+
|
||||
.vidioc_subscribe_event = vidioc_subscribe_evt,
|
||||
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
||||
|
||||
@@ -2546,6 +2586,8 @@ static int bcm2835_codec_create(struct platform_device *pdev,
|
||||
case DECODE:
|
||||
v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
|
||||
v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
|
||||
+ v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
|
||||
+ v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
|
||||
video_nr = decode_video_nr;
|
||||
break;
|
||||
case ENCODE:
|
||||
@@ -2558,6 +2600,8 @@ static int bcm2835_codec_create(struct platform_device *pdev,
|
||||
v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
|
||||
v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
|
||||
v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
|
||||
+ v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
|
||||
+ v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
|
||||
video_nr = isp_video_nr;
|
||||
break;
|
||||
default:
|
||||
--
|
||||
2.19.1
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From 9e064a15633a1e07b959e09af4d9d2df3dd0d450 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Wed, 12 Jun 2019 17:15:05 +0100
|
||||
Subject: [PATCH 525/528] w1: w1-gpio: Make GPIO an output for strong pullup
|
||||
|
||||
The logic to drive the data line high to implement a strong pullup
|
||||
assumed that the pin was already an output - setting a value does
|
||||
not change an input.
|
||||
|
||||
See: https://github.com/raspberrypi/firmware/issues/1143
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
drivers/w1/masters/w1-gpio.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
|
||||
index 55e11bf8ebaf..6327c88cfcc3 100644
|
||||
--- a/drivers/w1/masters/w1-gpio.c
|
||||
+++ b/drivers/w1/masters/w1-gpio.c
|
||||
@@ -33,7 +33,7 @@ static u8 w1_gpio_set_pullup(void *data, int delay)
|
||||
* This will OVERRIDE open drain emulation and force-pull
|
||||
* the line high for some time.
|
||||
*/
|
||||
- gpiod_set_raw_value(pdata->gpiod, 1);
|
||||
+ gpiod_direction_output_raw(pdata->gpiod, 1);
|
||||
msleep(pdata->pullup_duration);
|
||||
/*
|
||||
* This will simply set the line as input since we are doing
|
||||
--
|
||||
2.19.1
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
From f5645ab99474f9800e41544113333d5a7970b9d7 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Wed, 12 Jun 2019 17:32:11 +0100
|
||||
Subject: [PATCH 526/528] overlays: Update w1-gpio and w1-gpio-pullup
|
||||
|
||||
The parasitic power (power on data) feature is now enabled by
|
||||
default in the w1-gpio driver, so update the README and make the
|
||||
"pullup" parameter a no-op.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/README | 9 ++-------
|
||||
arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 3 +--
|
||||
arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts | 3 +--
|
||||
3 files changed, 4 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README
|
||||
index 42265637df37..c1863277cafb 100644
|
||||
--- a/arch/arm/boot/dts/overlays/README
|
||||
+++ b/arch/arm/boot/dts/overlays/README
|
||||
@@ -2261,9 +2261,7 @@ Info: Configures the w1-gpio Onewire interface module.
|
||||
Use this overlay if you *don't* need a GPIO to drive an external pullup.
|
||||
Load: dtoverlay=w1-gpio,<param>=<val>
|
||||
Params: gpiopin GPIO for I/O (default "4")
|
||||
-
|
||||
- pullup Non-zero, "on", or "y" to enable the parasitic
|
||||
- power (2-wire, power-on-data) feature
|
||||
+ pullup Now enabled by default (ignored)
|
||||
|
||||
|
||||
Name: w1-gpio-pullup
|
||||
@@ -2271,11 +2269,8 @@ Info: Configures the w1-gpio Onewire interface module.
|
||||
Use this overlay if you *do* need a GPIO to drive an external pullup.
|
||||
Load: dtoverlay=w1-gpio-pullup,<param>=<val>
|
||||
Params: gpiopin GPIO for I/O (default "4")
|
||||
-
|
||||
- pullup Non-zero, "on", or "y" to enable the parasitic
|
||||
- power (2-wire, power-on-data) feature
|
||||
-
|
||||
extpullup GPIO for external pullup (default "5")
|
||||
+ pullup Now enabled by default (ignored)
|
||||
|
||||
|
||||
Name: wittypi
|
||||
diff --git a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
|
||||
index 59543d69217e..f44e325bc1f2 100644
|
||||
--- a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
|
||||
@@ -14,7 +14,6 @@
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&w1_pins>;
|
||||
gpios = <&gpio 4 0>;
|
||||
- rpi,parasitic-power = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
@@ -36,6 +35,6 @@
|
||||
<&w1>,"reg:0",
|
||||
<&w1_pins>,"brcm,pins:0",
|
||||
<&w1_pins>,"reg:0";
|
||||
- pullup = <&w1>,"rpi,parasitic-power:0";
|
||||
+ pullup; // Silently ignore unneeded parameter
|
||||
};
|
||||
};
|
||||
diff --git a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
|
||||
index 000cf0150e43..953c6a1aeab9 100644
|
||||
--- a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
|
||||
@@ -14,7 +14,6 @@
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&w1_pins>;
|
||||
gpios = <&gpio 4 0>, <&gpio 5 1>;
|
||||
- rpi,parasitic-power = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
@@ -38,6 +37,6 @@
|
||||
<&w1_pins>,"reg:0";
|
||||
extpullup = <&w1>,"gpios:16",
|
||||
<&w1_pins>,"brcm,pins:4";
|
||||
- pullup = <&w1>,"rpi,parasitic-power:0";
|
||||
+ pullup; // Silently ignore unneeded parameter
|
||||
};
|
||||
};
|
||||
--
|
||||
2.19.1
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
From 5040b4b78e4cb74a6364d9a7c6cca0385e2dffd8 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Wed, 12 Jun 2019 20:45:17 +0100
|
||||
Subject: [PATCH 527/528] bcm2835-sdhost: Fix DMA channel leak on error/remove
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
drivers/mmc/host/bcm2835-sdhost.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c
|
||||
index d43af85135d3..844bed552bae 100644
|
||||
--- a/drivers/mmc/host/bcm2835-sdhost.c
|
||||
+++ b/drivers/mmc/host/bcm2835-sdhost.c
|
||||
@@ -2154,6 +2154,8 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev)
|
||||
|
||||
err:
|
||||
pr_debug("bcm2835_sdhost_probe -> err %d\n", ret);
|
||||
+ if (host->dma_chan_rxtx)
|
||||
+ dma_release_channel(host->dma_chan_rxtx);
|
||||
mmc_free_host(mmc);
|
||||
|
||||
return ret;
|
||||
@@ -2174,7 +2176,8 @@ static int bcm2835_sdhost_remove(struct platform_device *pdev)
|
||||
del_timer_sync(&host->timer);
|
||||
|
||||
tasklet_kill(&host->finish_tasklet);
|
||||
-
|
||||
+ if (host->dma_chan_rxtx)
|
||||
+ dma_release_channel(host->dma_chan_rxtx);
|
||||
mmc_free_host(host->mmc);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
From 2f8d963db206ce596f9a9e951ec425e9c3e1b4d9 Mon Sep 17 00:00:00 2001
|
||||
From: Annaliese McDermond <nh6z@nh6z.net>
|
||||
Date: Sat, 8 Jun 2019 10:14:43 -0700
|
||||
Subject: [PATCH 528/528] i2c: bcm2835: Model Divider in CCF
|
||||
|
||||
Commit bebff81fb8b9216eb4fba22cf910553621ae3477 upstream.
|
||||
|
||||
Model the I2C bus clock divider as a part of the Core Clock Framework.
|
||||
Primarily this removes the clk_get_rate() call from each transfer.
|
||||
This call causes problems for slave drivers that themselves have
|
||||
internal clock components that are controlled by an I2C interface.
|
||||
When the slave's internal clock component is prepared, the prepare
|
||||
lock is obtained, and it makes calls to the I2C subsystem to
|
||||
command the hardware to activate the clock. In order to perform
|
||||
the I2C transfer, this driver sets the divider, which requires
|
||||
it to get the parent clock rate, which it does with clk_get_rate().
|
||||
Unfortunately, this function will try to take the clock prepare
|
||||
lock, which is already held by the slave's internal clock calls
|
||||
creating a deadlock.
|
||||
|
||||
Modeling the divider in the CCF natively removes this dependency
|
||||
and the divider value is only set upon changing the bus clock
|
||||
frequency or changes in the parent clock that cascade down to this
|
||||
divisor. This obviates the need to set the divider with every
|
||||
transfer and avoids the deadlock described above. It also should
|
||||
provide better clock debugging and save a few cycles on each
|
||||
transfer due to not having to recalcuate the divider value.
|
||||
|
||||
Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
|
||||
Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
|
||||
Reviewed-by: Eric Anholt <eric@anholt.net>
|
||||
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
|
||||
---
|
||||
drivers/i2c/busses/i2c-bcm2835.c | 145 ++++++++++++++++++++++++-------
|
||||
1 file changed, 114 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
|
||||
index 1426dab2670b..108d2ae4632c 100644
|
||||
--- a/drivers/i2c/busses/i2c-bcm2835.c
|
||||
+++ b/drivers/i2c/busses/i2c-bcm2835.c
|
||||
@@ -12,6 +12,8 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
+#include <linux/clkdev.h>
|
||||
+#include <linux/clk-provider.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
@@ -71,9 +73,7 @@ struct bcm2835_debug {
|
||||
struct bcm2835_i2c_dev {
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
- struct clk *clk;
|
||||
int irq;
|
||||
- u32 bus_clk_rate;
|
||||
struct i2c_adapter adapter;
|
||||
struct completion completion;
|
||||
struct i2c_msg *curr_msg;
|
||||
@@ -164,12 +164,17 @@ static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg)
|
||||
return readl(i2c_dev->regs + reg);
|
||||
}
|
||||
|
||||
-static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev)
|
||||
+#define to_clk_bcm2835_i2c(_hw) container_of(_hw, struct clk_bcm2835_i2c, hw)
|
||||
+struct clk_bcm2835_i2c {
|
||||
+ struct clk_hw hw;
|
||||
+ struct bcm2835_i2c_dev *i2c_dev;
|
||||
+};
|
||||
+
|
||||
+static int clk_bcm2835_i2c_calc_divider(unsigned long rate,
|
||||
+ unsigned long parent_rate)
|
||||
{
|
||||
- u32 divider, redl, fedl;
|
||||
+ u32 divider = DIV_ROUND_UP(parent_rate, rate);
|
||||
|
||||
- divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk),
|
||||
- i2c_dev->bus_clk_rate);
|
||||
/*
|
||||
* Per the datasheet, the register is always interpreted as an even
|
||||
* number, by rounding down. In other words, the LSB is ignored. So,
|
||||
@@ -178,12 +183,23 @@ static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev)
|
||||
if (divider & 1)
|
||||
divider++;
|
||||
if ((divider < BCM2835_I2C_CDIV_MIN) ||
|
||||
- (divider > BCM2835_I2C_CDIV_MAX)) {
|
||||
- dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n");
|
||||
+ (divider > BCM2835_I2C_CDIV_MAX))
|
||||
return -EINVAL;
|
||||
- }
|
||||
|
||||
- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
|
||||
+ return divider;
|
||||
+}
|
||||
+
|
||||
+static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
|
||||
+ u32 redl, fedl;
|
||||
+ u32 divider = clk_bcm2835_i2c_calc_divider(rate, parent_rate);
|
||||
+
|
||||
+ if (divider == -EINVAL)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DIV, divider);
|
||||
|
||||
/*
|
||||
* Number of core clocks to wait after falling edge before
|
||||
@@ -198,12 +214,62 @@ static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev)
|
||||
*/
|
||||
redl = max(divider / 4, 1u);
|
||||
|
||||
- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DEL,
|
||||
+ bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DEL,
|
||||
(fedl << BCM2835_I2C_FEDL_SHIFT) |
|
||||
(redl << BCM2835_I2C_REDL_SHIFT));
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static long clk_bcm2835_i2c_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
+ unsigned long *parent_rate)
|
||||
+{
|
||||
+ u32 divider = clk_bcm2835_i2c_calc_divider(rate, *parent_rate);
|
||||
+
|
||||
+ return DIV_ROUND_UP(*parent_rate, divider);
|
||||
+}
|
||||
+
|
||||
+static unsigned long clk_bcm2835_i2c_recalc_rate(struct clk_hw *hw,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
|
||||
+ u32 divider = bcm2835_i2c_readl(div->i2c_dev, BCM2835_I2C_DIV);
|
||||
+
|
||||
+ return DIV_ROUND_UP(parent_rate, divider);
|
||||
+}
|
||||
+
|
||||
+static const struct clk_ops clk_bcm2835_i2c_ops = {
|
||||
+ .set_rate = clk_bcm2835_i2c_set_rate,
|
||||
+ .round_rate = clk_bcm2835_i2c_round_rate,
|
||||
+ .recalc_rate = clk_bcm2835_i2c_recalc_rate,
|
||||
+};
|
||||
+
|
||||
+static struct clk *bcm2835_i2c_register_div(struct device *dev,
|
||||
+ const char *mclk_name,
|
||||
+ struct bcm2835_i2c_dev *i2c_dev)
|
||||
+{
|
||||
+ struct clk_init_data init;
|
||||
+ struct clk_bcm2835_i2c *priv;
|
||||
+ char name[32];
|
||||
+
|
||||
+ snprintf(name, sizeof(name), "%s_div", dev_name(dev));
|
||||
+
|
||||
+ init.ops = &clk_bcm2835_i2c_ops;
|
||||
+ init.name = name;
|
||||
+ init.parent_names = (const char* []) { mclk_name };
|
||||
+ init.num_parents = 1;
|
||||
+ init.flags = 0;
|
||||
+
|
||||
+ priv = devm_kzalloc(dev, sizeof(struct clk_bcm2835_i2c), GFP_KERNEL);
|
||||
+ if (priv == NULL)
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+
|
||||
+ priv->hw.init = &init;
|
||||
+ priv->i2c_dev = i2c_dev;
|
||||
+
|
||||
+ clk_hw_register_clkdev(&priv->hw, "div", dev_name(dev));
|
||||
+ return devm_clk_register(dev, &priv->hw);
|
||||
+}
|
||||
+
|
||||
static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
|
||||
{
|
||||
u32 val;
|
||||
@@ -363,7 +429,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
|
||||
{
|
||||
struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
|
||||
unsigned long time_left;
|
||||
- int i, ret;
|
||||
+ int i;
|
||||
|
||||
if (debug)
|
||||
i2c_dev->debug_num_msgs = num;
|
||||
@@ -379,10 +445,6 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
- ret = bcm2835_i2c_set_divider(i2c_dev);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
i2c_dev->curr_msg = msgs;
|
||||
i2c_dev->num_msgs = num;
|
||||
reinit_completion(&i2c_dev->completion);
|
||||
@@ -443,6 +505,9 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
|
||||
struct resource *mem, *irq;
|
||||
int ret;
|
||||
struct i2c_adapter *adap;
|
||||
+ const char *mclk_name;
|
||||
+ struct clk *bus_clk;
|
||||
+ u32 bus_clk_rate;
|
||||
|
||||
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
|
||||
if (!i2c_dev)
|
||||
@@ -456,21 +521,6 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(i2c_dev->regs))
|
||||
return PTR_ERR(i2c_dev->regs);
|
||||
|
||||
- i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
- if (IS_ERR(i2c_dev->clk)) {
|
||||
- if (PTR_ERR(i2c_dev->clk) != -EPROBE_DEFER)
|
||||
- dev_err(&pdev->dev, "Could not get clock\n");
|
||||
- return PTR_ERR(i2c_dev->clk);
|
||||
- }
|
||||
-
|
||||
- ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
|
||||
- &i2c_dev->bus_clk_rate);
|
||||
- if (ret < 0) {
|
||||
- dev_warn(&pdev->dev,
|
||||
- "Could not read clock-frequency property\n");
|
||||
- i2c_dev->bus_clk_rate = 100000;
|
||||
- }
|
||||
-
|
||||
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!irq) {
|
||||
dev_err(&pdev->dev, "No IRQ resource\n");
|
||||
@@ -485,6 +535,35 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
+ mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
|
||||
+
|
||||
+ bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
|
||||
+
|
||||
+ if (IS_ERR(bus_clk)) {
|
||||
+ dev_err(&pdev->dev, "Could not register clock\n");
|
||||
+ return PTR_ERR(bus_clk);
|
||||
+ }
|
||||
+
|
||||
+ ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
|
||||
+ &bus_clk_rate);
|
||||
+ if (ret < 0) {
|
||||
+ dev_warn(&pdev->dev,
|
||||
+ "Could not read clock-frequency property\n");
|
||||
+ bus_clk_rate = 100000;
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_set_rate_exclusive(bus_clk, bus_clk_rate);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(&pdev->dev, "Could not set clock frequency\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_prepare_enable(bus_clk);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "Couldn't prepare clock");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
adap = &i2c_dev->adapter;
|
||||
i2c_set_adapdata(adap, i2c_dev);
|
||||
adap->owner = THIS_MODULE;
|
||||
@@ -507,6 +586,10 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
|
||||
static int bcm2835_i2c_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
|
||||
+ struct clk *bus_clk = devm_clk_get(i2c_dev->dev, "div");
|
||||
+
|
||||
+ clk_rate_exclusive_put(bus_clk);
|
||||
+ clk_disable_unprepare(bus_clk);
|
||||
|
||||
free_irq(i2c_dev->irq, i2c_dev);
|
||||
i2c_del_adapter(&i2c_dev->adapter);
|
||||
--
|
||||
2.19.1
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue