mirror of
https://github.com/smaeul/u-boot.git
synced 2025-10-17 14:18:14 +01:00
reset: sunxi: Reuse the platform data from the clock driver
The clock and reset drivers use the exact same platform data. Simplify them by sharing the object. This is safe because the parent device (the clock device) always gets its driver model callbacks run first. Series-to: sunxi Series-cc: Lukasz Majewski <lukma@denx.de> Series-cc: Sean Anderson <seanga2@gmail.com> Series-version: 2 Cover-letter: clk: sunxi: Out-of-bounds access fix and driver cleanup This series fixes an issue with out-of-bounds access to the gate array (patches 1-2), uses the rearranged array size information to remove a bunch of duplicate code (patches 3-4), and then simplifies how the reset driver is bound (patches 5-7). The original motivation for these changes was adding a driver for the legacy A31/A23/A33 PRCM binding (which I will send separately), and trying to use OF_PLATDATA in SPL (which did not work out). But I think at least some of the cleanup is worth applying on its own. Patch 4 is generally the same change I made between v1 and v2 of the pinctrl series, using some #ifdefs to share a U_BOOT_DRIVER. It's not quite as clean as the pinctrl case, because here the SoC-specific parts are in different files, so all of the CCU descriptors have to be global. END Acked-by: Sean Anderson <seanga2@gmail.com> Signed-off-by: Samuel Holland <samuel@sholland.org>
This commit is contained in:
parent
7c576b083b
commit
d4a4d63a0b
@ -12,9 +12,12 @@
|
||||
#include <reset.h>
|
||||
#include <asm/io.h>
|
||||
#include <clk/sunxi.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/log2.h>
|
||||
|
||||
extern U_BOOT_DRIVER(sunxi_reset);
|
||||
|
||||
static const struct ccu_clk_gate *plat_to_gate(struct ccu_plat *plat,
|
||||
unsigned long id)
|
||||
{
|
||||
@ -67,7 +70,9 @@ struct clk_ops sunxi_clk_ops = {
|
||||
|
||||
static int sunxi_clk_bind(struct udevice *dev)
|
||||
{
|
||||
return sunxi_reset_bind(dev);
|
||||
/* Reuse the platform data for the reset driver. */
|
||||
return device_bind(dev, DM_DRIVER_REF(sunxi_reset), "reset",
|
||||
dev_get_plat(dev), dev_ofnode(dev), NULL);
|
||||
}
|
||||
|
||||
static int sunxi_clk_probe(struct udevice *dev)
|
||||
|
@ -12,17 +12,10 @@
|
||||
#include <reset-uclass.h>
|
||||
#include <asm/io.h>
|
||||
#include <clk/sunxi.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/lists.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/log2.h>
|
||||
|
||||
struct sunxi_reset_plat {
|
||||
void *base;
|
||||
const struct ccu_desc *desc;
|
||||
};
|
||||
|
||||
static const struct ccu_reset *plat_to_reset(struct sunxi_reset_plat *plat,
|
||||
static const struct ccu_reset *plat_to_reset(struct ccu_plat *plat,
|
||||
unsigned long id)
|
||||
{
|
||||
return &plat->desc->resets[id];
|
||||
@ -30,7 +23,7 @@ static const struct ccu_reset *plat_to_reset(struct sunxi_reset_plat *plat,
|
||||
|
||||
static int sunxi_reset_request(struct reset_ctl *reset_ctl)
|
||||
{
|
||||
struct sunxi_reset_plat *plat = dev_get_plat(reset_ctl->dev);
|
||||
struct ccu_plat *plat = dev_get_plat(reset_ctl->dev);
|
||||
|
||||
debug("%s: (RST#%ld)\n", __func__, reset_ctl->id);
|
||||
|
||||
@ -42,7 +35,7 @@ static int sunxi_reset_request(struct reset_ctl *reset_ctl)
|
||||
|
||||
static int sunxi_set_reset(struct reset_ctl *reset_ctl, bool on)
|
||||
{
|
||||
struct sunxi_reset_plat *plat = dev_get_plat(reset_ctl->dev);
|
||||
struct ccu_plat *plat = dev_get_plat(reset_ctl->dev);
|
||||
const struct ccu_reset *reset = plat_to_reset(plat, reset_ctl->id);
|
||||
u32 reg;
|
||||
|
||||
@ -81,38 +74,8 @@ struct reset_ops sunxi_reset_ops = {
|
||||
.rst_deassert = sunxi_reset_deassert,
|
||||
};
|
||||
|
||||
static int sunxi_reset_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
struct sunxi_reset_plat *plat = dev_get_plat(dev);
|
||||
|
||||
plat->base = dev_read_addr_ptr(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sunxi_reset_bind(struct udevice *dev)
|
||||
{
|
||||
struct udevice *rst_dev;
|
||||
struct sunxi_reset_plat *plat;
|
||||
int ret;
|
||||
|
||||
ret = device_bind_driver_to_node(dev, "sunxi_reset", "reset",
|
||||
dev_ofnode(dev), &rst_dev);
|
||||
if (ret) {
|
||||
debug("failed to bind sunxi_reset driver (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
plat = malloc(sizeof(struct sunxi_reset_plat));
|
||||
plat->desc = (const struct ccu_desc *)dev_get_driver_data(dev);
|
||||
dev_set_plat(rst_dev, plat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(sunxi_reset) = {
|
||||
.name = "sunxi_reset",
|
||||
.id = UCLASS_RESET,
|
||||
.ops = &sunxi_reset_ops,
|
||||
.of_to_plat = sunxi_reset_of_to_plat,
|
||||
.plat_auto = sizeof(struct sunxi_reset_plat),
|
||||
};
|
||||
|
@ -87,12 +87,4 @@ struct ccu_plat {
|
||||
|
||||
extern struct clk_ops sunxi_clk_ops;
|
||||
|
||||
/**
|
||||
* sunxi_reset_bind() - reset binding
|
||||
*
|
||||
* @dev: reset device
|
||||
* Return: 0 success, or error value
|
||||
*/
|
||||
int sunxi_reset_bind(struct udevice *dev);
|
||||
|
||||
#endif /* _CLK_SUNXI_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user