pinctrl: single: Prepare for supporting SoC specific features
Let's replace is_pinconf with flags and add struct pcs_soc_data so we can support SoC specific features like pin wake-up events. Done in collaboration with Roger Quadros <rogerq@ti.com>. Cc: Peter Ujfalusi <peter.ujfalusi@ti.com> Cc: Grygorii Strashko <grygorii.strashko@ti.com> Cc: Prakash Manjunathappa <prakash.pm@ti.com> Cc: linux-kernel@vger.kernel.org Acked-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com> Reviewed-by: Kevin Hilman <khilman@linaro.org> Tested-by: Kevin Hilman <khilman@linaro.org> Signed-off-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
This commit is contained in:
@@ -149,6 +149,14 @@ struct pcs_name {
|
|||||||
char name[PCS_REG_NAME_LEN];
|
char name[PCS_REG_NAME_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct pcs_soc_data - SoC specific settings
|
||||||
|
* @flags: initial SoC specific PCS_FEAT_xxx values
|
||||||
|
*/
|
||||||
|
struct pcs_soc_data {
|
||||||
|
unsigned flags;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct pcs_device - pinctrl device instance
|
* struct pcs_device - pinctrl device instance
|
||||||
* @res: resources
|
* @res: resources
|
||||||
@@ -156,13 +164,13 @@ struct pcs_name {
|
|||||||
* @size: size of the ioremapped area
|
* @size: size of the ioremapped area
|
||||||
* @dev: device entry
|
* @dev: device entry
|
||||||
* @pctl: pin controller device
|
* @pctl: pin controller device
|
||||||
|
* @flags: mask of PCS_FEAT_xxx values
|
||||||
* @mutex: mutex protecting the lists
|
* @mutex: mutex protecting the lists
|
||||||
* @width: bits per mux register
|
* @width: bits per mux register
|
||||||
* @fmask: function register mask
|
* @fmask: function register mask
|
||||||
* @fshift: function register shift
|
* @fshift: function register shift
|
||||||
* @foff: value to turn mux off
|
* @foff: value to turn mux off
|
||||||
* @fmax: max number of functions in fmask
|
* @fmax: max number of functions in fmask
|
||||||
* @is_pinconf: whether supports pinconf
|
|
||||||
* @bits_per_pin:number of bits per pin
|
* @bits_per_pin:number of bits per pin
|
||||||
* @names: array of register names for pins
|
* @names: array of register names for pins
|
||||||
* @pins: physical pins on the SoC
|
* @pins: physical pins on the SoC
|
||||||
@@ -183,6 +191,8 @@ struct pcs_device {
|
|||||||
unsigned size;
|
unsigned size;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct pinctrl_dev *pctl;
|
struct pinctrl_dev *pctl;
|
||||||
|
unsigned flags;
|
||||||
|
#define PCS_FEAT_PINCONF (1 << 0)
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
unsigned width;
|
unsigned width;
|
||||||
unsigned fmask;
|
unsigned fmask;
|
||||||
@@ -190,7 +200,6 @@ struct pcs_device {
|
|||||||
unsigned foff;
|
unsigned foff;
|
||||||
unsigned fmax;
|
unsigned fmax;
|
||||||
bool bits_per_mux;
|
bool bits_per_mux;
|
||||||
bool is_pinconf;
|
|
||||||
unsigned bits_per_pin;
|
unsigned bits_per_pin;
|
||||||
struct pcs_name *names;
|
struct pcs_name *names;
|
||||||
struct pcs_data pins;
|
struct pcs_data pins;
|
||||||
@@ -206,6 +215,8 @@ struct pcs_device {
|
|||||||
void (*write)(unsigned val, void __iomem *reg);
|
void (*write)(unsigned val, void __iomem *reg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define PCS_HAS_PINCONF (pcs->flags & PCS_FEAT_PINCONF)
|
||||||
|
|
||||||
static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
|
static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
|
||||||
unsigned long *config);
|
unsigned long *config);
|
||||||
static int pcs_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
|
static int pcs_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
|
||||||
@@ -1060,7 +1071,7 @@ static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np,
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* If pinconf isn't supported, don't parse properties in below. */
|
/* If pinconf isn't supported, don't parse properties in below. */
|
||||||
if (!pcs->is_pinconf)
|
if (!PCS_HAS_PINCONF)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* cacluate how much properties are supported in current node */
|
/* cacluate how much properties are supported in current node */
|
||||||
@@ -1184,7 +1195,7 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
|
|||||||
(*map)->data.mux.group = np->name;
|
(*map)->data.mux.group = np->name;
|
||||||
(*map)->data.mux.function = np->name;
|
(*map)->data.mux.function = np->name;
|
||||||
|
|
||||||
if (pcs->is_pinconf) {
|
if (PCS_HAS_PINCONF) {
|
||||||
res = pcs_parse_pinconf(pcs, np, function, map);
|
res = pcs_parse_pinconf(pcs, np, function, map);
|
||||||
if (res)
|
if (res)
|
||||||
goto free_pingroups;
|
goto free_pingroups;
|
||||||
@@ -1305,7 +1316,7 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
|
|||||||
(*map)->data.mux.group = np->name;
|
(*map)->data.mux.group = np->name;
|
||||||
(*map)->data.mux.function = np->name;
|
(*map)->data.mux.function = np->name;
|
||||||
|
|
||||||
if (pcs->is_pinconf) {
|
if (PCS_HAS_PINCONF) {
|
||||||
dev_err(pcs->dev, "pinconf not supported\n");
|
dev_err(pcs->dev, "pinconf not supported\n");
|
||||||
goto free_pingroups;
|
goto free_pingroups;
|
||||||
}
|
}
|
||||||
@@ -1525,6 +1536,7 @@ static int pcs_probe(struct platform_device *pdev)
|
|||||||
const struct of_device_id *match;
|
const struct of_device_id *match;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
struct pcs_device *pcs;
|
struct pcs_device *pcs;
|
||||||
|
const struct pcs_soc_data *soc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
match = of_match_device(pcs_of_match, &pdev->dev);
|
match = of_match_device(pcs_of_match, &pdev->dev);
|
||||||
@@ -1541,7 +1553,8 @@ static int pcs_probe(struct platform_device *pdev)
|
|||||||
INIT_LIST_HEAD(&pcs->pingroups);
|
INIT_LIST_HEAD(&pcs->pingroups);
|
||||||
INIT_LIST_HEAD(&pcs->functions);
|
INIT_LIST_HEAD(&pcs->functions);
|
||||||
INIT_LIST_HEAD(&pcs->gpiofuncs);
|
INIT_LIST_HEAD(&pcs->gpiofuncs);
|
||||||
pcs->is_pinconf = match->data;
|
soc = match->data;
|
||||||
|
pcs->flags = soc->flags;
|
||||||
|
|
||||||
PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width,
|
PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width,
|
||||||
"register width not specified\n");
|
"register width not specified\n");
|
||||||
@@ -1610,7 +1623,7 @@ static int pcs_probe(struct platform_device *pdev)
|
|||||||
pcs->desc.name = DRIVER_NAME;
|
pcs->desc.name = DRIVER_NAME;
|
||||||
pcs->desc.pctlops = &pcs_pinctrl_ops;
|
pcs->desc.pctlops = &pcs_pinctrl_ops;
|
||||||
pcs->desc.pmxops = &pcs_pinmux_ops;
|
pcs->desc.pmxops = &pcs_pinmux_ops;
|
||||||
if (pcs->is_pinconf)
|
if (PCS_HAS_PINCONF)
|
||||||
pcs->desc.confops = &pcs_pinconf_ops;
|
pcs->desc.confops = &pcs_pinconf_ops;
|
||||||
pcs->desc.owner = THIS_MODULE;
|
pcs->desc.owner = THIS_MODULE;
|
||||||
|
|
||||||
@@ -1652,9 +1665,16 @@ static int pcs_remove(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct pcs_soc_data pinctrl_single = {
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pcs_soc_data pinconf_single = {
|
||||||
|
.flags = PCS_FEAT_PINCONF,
|
||||||
|
};
|
||||||
|
|
||||||
static struct of_device_id pcs_of_match[] = {
|
static struct of_device_id pcs_of_match[] = {
|
||||||
{ .compatible = "pinctrl-single", .data = (void *)false },
|
{ .compatible = "pinctrl-single", .data = &pinctrl_single },
|
||||||
{ .compatible = "pinconf-single", .data = (void *)true },
|
{ .compatible = "pinconf-single", .data = &pinconf_single },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, pcs_of_match);
|
MODULE_DEVICE_TABLE(of, pcs_of_match);
|
||||||
|
Reference in New Issue
Block a user