1
0
Fork 0
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:
Ycarus (Yannick Chabanois) 2019-06-18 18:43:58 +02:00
parent dfd30fd2b8
commit f1e3dc3f73
37 changed files with 767 additions and 2695 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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