/* * Find the correct struct clk for the device and connection ID. * We do slightly fuzzy matching here: * An entry with a NULL ID is assumed to be a wildcard. * If an entry has a device ID, it must match * If an entry has a connection ID, it must match * Then we take the most specific entry - with the following * order of precedence: dev+con > dev only > con only.
*/ staticstruct clk_lookup *clk_find(constchar *dev_id, constchar *con_id)
{ struct clk_lookup *p, *cl = NULL; int match, best_found = 0, best_possible = 0;
if (dev_id)
best_possible += 2; if (con_id)
best_possible += 1;
lockdep_assert_held(&clocks_mutex);
list_for_each_entry(p, &clocks, node) {
match = 0; if (p->dev_id) { if (!dev_id || strcmp(p->dev_id, dev_id)) continue;
match += 2;
} if (p->con_id) { if (!con_id || strcmp(p->con_id, con_id)) continue;
match += 1;
}
cla = kzalloc(sizeof(*cla), GFP_KERNEL); if (!cla) return NULL;
va_copy(ap_copy, ap);
cla->cl.clk_hw = hw; if (con_id) {
res = strscpy(cla->con_id, con_id, sizeof(cla->con_id)); if (res < 0) {
max_size = sizeof(cla->con_id);
failure = "connection"; goto fail;
}
cla->cl.con_id = cla->con_id;
}
if (dev_fmt) {
res = vsnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap); if (res >= sizeof(cla->dev_id)) {
max_size = sizeof(cla->dev_id);
failure = "device"; goto fail;
}
cla->cl.dev_id = cla->dev_id;
}
va_end(ap_copy);
return &cla->cl;
fail: if (dev_fmt)
vaf.fmt = dev_fmt; else
vaf.fmt = "null-device";
vaf.va = &ap_copy;
pr_err("%pV:%s: %s ID is greater than %zu\n",
&vaf, con_id, failure, max_size);
va_end(ap_copy);
/* * Don't fail in this case, but as the entry won't ever match just * fill it with something that also won't match.
*/
strscpy(cla->con_id, "bad", sizeof(cla->con_id));
strscpy(cla->dev_id, "bad", sizeof(cla->dev_id));
cl = vclkdev_alloc(hw, con_id, dev_fmt, ap); if (cl)
__clkdev_add(cl);
return cl;
}
/** * clkdev_create - allocate and add a clkdev lookup structure * @clk: struct clk to associate with all clk_lookups * @con_id: connection ID string on device * @dev_fmt: format string describing device name * * Returns a clk_lookup structure, which can be later unregistered and * freed.
*/ struct clk_lookup *clkdev_create(struct clk *clk, constchar *con_id, constchar *dev_fmt, ...)
{ struct clk_lookup *cl;
va_list ap;
/** * clkdev_hw_create - allocate and add a clkdev lookup structure * @hw: struct clk_hw to associate with all clk_lookups * @con_id: connection ID string on device * @dev_fmt: format string describing device name * * Returns a clk_lookup structure, which can be later unregistered and * freed.
*/ struct clk_lookup *clkdev_hw_create(struct clk_hw *hw, constchar *con_id, constchar *dev_fmt, ...)
{ struct clk_lookup *cl;
va_list ap;
staticint do_clk_register_clkdev(struct clk_hw *hw, struct clk_lookup **cl, constchar *con_id, constchar *dev_id)
{ if (IS_ERR(hw)) return PTR_ERR(hw); /* * Since dev_id can be NULL, and NULL is handled specially, we must * pass it as either a NULL format string, or with "%s".
*/ if (dev_id)
*cl = __clk_register_clkdev(hw, con_id, "%s", dev_id); else
*cl = __clk_register_clkdev(hw, con_id, NULL);
return *cl ? 0 : -ENOMEM;
}
/** * clk_register_clkdev - register one clock lookup for a struct clk * @clk: struct clk to associate with all clk_lookups * @con_id: connection ID string on device * @dev_id: string describing device name * * con_id or dev_id may be NULL as a wildcard, just as in the rest of * clkdev. * * To make things easier for mass registration, we detect error clks * from a previous clk_register() call, and return the error code for * those. This is to permit this function to be called immediately * after clk_register().
*/ int clk_register_clkdev(struct clk *clk, constchar *con_id, constchar *dev_id)
{ struct clk_lookup *cl;
/** * clk_hw_register_clkdev - register one clock lookup for a struct clk_hw * @hw: struct clk_hw to associate with all clk_lookups * @con_id: connection ID string on device * @dev_id: format string describing device name * * con_id or dev_id may be NULL as a wildcard, just as in the rest of * clkdev. * * To make things easier for mass registration, we detect error clk_hws * from a previous clk_hw_register_*() call, and return the error code for * those. This is to permit this function to be called immediately * after clk_hw_register_*().
*/ int clk_hw_register_clkdev(struct clk_hw *hw, constchar *con_id, constchar *dev_id)
{ struct clk_lookup *cl;
/** * devm_clk_hw_register_clkdev - managed clk lookup registration for clk_hw * @dev: device this lookup is bound * @hw: struct clk_hw to associate with all clk_lookups * @con_id: connection ID string on device * @dev_id: format string describing device name * * con_id or dev_id may be NULL as a wildcard, just as in the rest of * clkdev. * * To make things easier for mass registration, we detect error clk_hws * from a previous clk_hw_register_*() call, and return the error code for * those. This is to permit this function to be called immediately * after clk_hw_register_*().
*/ int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw, constchar *con_id, constchar *dev_id)
{ struct clk_lookup *cl; int rval;
rval = do_clk_register_clkdev(hw, &cl, con_id, dev_id); if (rval) return rval;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.