Many SoCs have a number of system controllers which are dealt with as a group by a single driver. It is a pain to have to add lots of compatible strings and/or separate drivers for each. Instead we can identify the controllers by a number and request the address of the one we want. Add a simple implementation of this which can be used by SoC driver code. Signed-off-by: Simon Glass <sjg@chromium.org>master
parent
6f98b7504f
commit
5725128507
@ -0,0 +1,73 @@ |
||||
/*
|
||||
* Copyright (C) 2015 Google, Inc |
||||
* Written by Simon Glass <sjg@chromium.org> |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <syscon.h> |
||||
#include <dm.h> |
||||
#include <errno.h> |
||||
#include <regmap.h> |
||||
#include <dm/device-internal.h> |
||||
#include <dm/lists.h> |
||||
#include <dm/root.h> |
||||
#include <linux/err.h> |
||||
|
||||
struct regmap *syscon_get_regmap(struct udevice *dev) |
||||
{ |
||||
struct syscon_uc_info *priv = dev_get_uclass_priv(dev); |
||||
|
||||
return priv->regmap; |
||||
} |
||||
|
||||
static int syscon_pre_probe(struct udevice *dev) |
||||
{ |
||||
struct syscon_uc_info *priv = dev_get_uclass_priv(dev); |
||||
|
||||
return regmap_init_mem(dev, &priv->regmap); |
||||
} |
||||
|
||||
struct regmap *syscon_get_regmap_by_driver_data(ulong driver_data) |
||||
{ |
||||
struct udevice *dev; |
||||
struct uclass *uc; |
||||
int ret; |
||||
|
||||
ret = uclass_get(UCLASS_SYSCON, &uc); |
||||
if (ret) |
||||
return ERR_PTR(ret); |
||||
uclass_foreach_dev(dev, uc) { |
||||
if (dev->driver_data == driver_data) { |
||||
struct syscon_uc_info *priv; |
||||
int ret; |
||||
|
||||
ret = device_probe(dev); |
||||
if (ret) |
||||
return ERR_PTR(ret); |
||||
priv = dev_get_uclass_priv(dev); |
||||
|
||||
return priv->regmap; |
||||
} |
||||
} |
||||
|
||||
return ERR_PTR(-ENOENT); |
||||
} |
||||
|
||||
void *syscon_get_first_range(ulong driver_data) |
||||
{ |
||||
struct regmap *map; |
||||
|
||||
map = syscon_get_regmap_by_driver_data(driver_data); |
||||
if (IS_ERR(map)) |
||||
return map; |
||||
return regmap_get_range(map, 0); |
||||
} |
||||
|
||||
UCLASS_DRIVER(syscon) = { |
||||
.id = UCLASS_SYSCON, |
||||
.name = "syscon", |
||||
.per_device_auto_alloc_size = sizeof(struct syscon_uc_info), |
||||
.pre_probe = syscon_pre_probe, |
||||
}; |
@ -0,0 +1,56 @@ |
||||
/*
|
||||
* Copyright (c) 2015 Google, Inc |
||||
* Written by Simon Glass <sjg@chromium.org> |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#ifndef __SYSCON_H |
||||
#define __SYSCON_H |
||||
|
||||
/**
|
||||
* struct syscon_uc_info - Information stored by the syscon UCLASS_UCLASS |
||||
* |
||||
* @regmap: Register map for this controller |
||||
*/ |
||||
struct syscon_uc_info { |
||||
struct regmap *regmap; |
||||
}; |
||||
|
||||
/* So far there are no ops so this is a placeholder */ |
||||
struct syscon_ops { |
||||
}; |
||||
|
||||
#define syscon_get_ops(dev) ((struct syscon_ops *)(dev)->driver->ops) |
||||
|
||||
/**
|
||||
* syscon_get_regmap() - Get access to a register map |
||||
* |
||||
* @dev: Device to check (UCLASS_SCON) |
||||
* @info: Returns regmap for the device |
||||
* @return 0 if OK, -ve on error |
||||
*/ |
||||
struct regmap *syscon_get_regmap(struct udevice *dev); |
||||
|
||||
/**
|
||||
* syscon_get_regmap_by_driver_data() - Look up a controller by its ID |
||||
* |
||||
* Each system controller can be accessed by its driver data, which is |
||||
* assumed to be unique through the scope of all system controllers that |
||||
* are in use. This function looks up the regmap given this driver data. |
||||
* |
||||
* @driver_data: Driver data value to look up |
||||
* @return register map correponding to @driver_data, or -ve error code |
||||
*/ |
||||
struct regmap *syscon_get_regmap_by_driver_data(ulong driver_data); |
||||
|
||||
/**
|
||||
* syscon_get_first_range() - get the first memory range from a syscon regmap |
||||
* |
||||
* @driver_data: Driver data value to look up |
||||
* @return first region of register map correponding to @driver_data, or |
||||
* -ve error code |
||||
*/ |
||||
void *syscon_get_first_range(ulong driver_data); |
||||
|
||||
#endif |
Loading…
Reference in new issue