/** * zl3073x_pin_check_freq - verify frequency for given pin * @zldev: pointer to zl3073x device * @dir: pin direction * @id: pin index * @freq: frequency to check * * The function checks the given frequency is valid for the device. For input * pins it checks that the frequency can be factorized using supported base * frequencies. For output pins it checks that the frequency divides connected * synth frequency without remainder. * * Return: true if the frequency is valid, false if not.
*/ staticbool
zl3073x_pin_check_freq(struct zl3073x_dev *zldev, enum dpll_pin_direction dir,
u8 id, u64 freq)
{ if (freq > U32_MAX) goto err_inv_freq;
if (dir == DPLL_PIN_DIRECTION_INPUT) { int rc;
/* Check if the frequency can be factorized */
rc = zl3073x_ref_freq_factorize(freq, NULL, NULL); if (rc) goto err_inv_freq;
} else {
u32 synth_freq;
u8 out, synth;
/* Get output pin synthesizer */
out = zl3073x_output_pin_out_get(id);
synth = zl3073x_out_synth_get(zldev, out);
/* Get synth frequency */
synth_freq = zl3073x_synth_freq_get(zldev, synth);
/* Check the frequency divides synth frequency */ if (synth_freq % (u32)freq) goto err_inv_freq;
}
returntrue;
err_inv_freq:
dev_warn(zldev->dev, "Unsupported frequency %llu Hz in firmware node\n", freq);
returnfalse;
}
/** * zl3073x_prop_pin_package_label_set - get package label for the pin * @zldev: pointer to zl3073x device * @props: pointer to pin properties * @dir: pin direction * @id: pin index * * Generates package label string and stores it into pin properties structure. * * Possible formats: * REF<n> - differential input reference * REF<n>P & REF<n>N - single-ended input reference (P or N pin) * OUT<n> - differential output * OUT<n>P & OUT<n>N - single-ended output (P or N pin)
*/ staticvoid
zl3073x_prop_pin_package_label_set(struct zl3073x_dev *zldev, struct zl3073x_pin_props *props, enum dpll_pin_direction dir, u8 id)
{ constchar *prefix, *suffix; bool is_diff;
/** * zl3073x_pin_props_get - get pin properties * @zldev: pointer to zl3073x device * @dir: pin direction * @index: pin index * * The function looks for firmware node for the given pin if it is provided * by the system firmware (DT or ACPI), allocates pin properties structure, * generates package label string according pin type and optionally fetches * board label, connection type, supported frequencies and esync capability * from the firmware node if it does exist. * * Pointer that is returned by this function should be freed using * @zl3073x_pin_props_put(). * * Return: * * pointer to allocated pin properties structure on success * * error pointer in case of error
*/ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev, enum dpll_pin_direction dir,
u8 index)
{ struct dpll_pin_frequency *ranges; struct zl3073x_pin_props *props; int i, j, num_freqs, rc; constchar *type;
u64 *freqs;
props = kzalloc(sizeof(*props), GFP_KERNEL); if (!props) return ERR_PTR(-ENOMEM);
/* Set default pin type and capabilities */ if (dir == DPLL_PIN_DIRECTION_INPUT) {
props->dpll_props.type = DPLL_PIN_TYPE_EXT;
props->dpll_props.capabilities =
DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE |
DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
} else {
props->dpll_props.type = DPLL_PIN_TYPE_GNSS;
}
/* Get firmware node for the given pin */
rc = zl3073x_prop_pin_fwnode_get(zldev, props, dir, index); if (rc) return props; /* Return if it does not exist */
/* Look for label property and store the value as board label */
fwnode_property_read_string(props->fwnode, "label",
&props->dpll_props.board_label);
/* Look for pin type property and translate its value to DPLL * pin type enum if it is present.
*/ if (!fwnode_property_read_string(props->fwnode, "connection-type",
&type)) { if (!strcmp(type, "ext"))
props->dpll_props.type = DPLL_PIN_TYPE_EXT; elseif (!strcmp(type, "gnss"))
props->dpll_props.type = DPLL_PIN_TYPE_GNSS; elseif (!strcmp(type, "int"))
props->dpll_props.type = DPLL_PIN_TYPE_INT_OSCILLATOR; elseif (!strcmp(type, "synce"))
props->dpll_props.type = DPLL_PIN_TYPE_SYNCE_ETH_PORT; else
dev_warn(zldev->dev, "Unknown or unsupported pin type '%s'\n",
type);
}
/* Check if the pin supports embedded sync control */
props->esync_control = fwnode_property_read_bool(props->fwnode, "esync-control");
/* Read supported frequencies property if it is specified */
num_freqs = fwnode_property_count_u64(props->fwnode, "supported-frequencies-hz"); if (num_freqs <= 0) /* Return if the property does not exist or number is 0 */ return props;
/* The firmware node specifies list of supported frequencies while * DPLL core pin properties requires list of frequency ranges. * So read the frequency list into temporary array.
*/
freqs = kcalloc(num_freqs, sizeof(*freqs), GFP_KERNEL); if (!freqs) {
rc = -ENOMEM; goto err_alloc_freqs;
}
/* Read frequencies list from firmware node */
fwnode_property_read_u64_array(props->fwnode, "supported-frequencies-hz", freqs,
num_freqs);
/* Allocate frequency ranges list and fill it */
ranges = kcalloc(num_freqs, sizeof(*ranges), GFP_KERNEL); if (!ranges) {
rc = -ENOMEM; goto err_alloc_ranges;
}
/* Convert list of frequencies to list of frequency ranges but * filter-out frequencies that are not representable by device
*/ for (i = 0, j = 0; i < num_freqs; i++) { struct dpll_pin_frequency freq = DPLL_PIN_FREQUENCY(freqs[i]);
/* Save number of freq ranges and pointer to them into pin properties */
props->dpll_props.freq_supported = ranges;
props->dpll_props.freq_supported_num = j;
/** * zl3073x_pin_props_put - release pin properties * @props: pin properties to free * * The function deallocates given pin properties structure.
*/ void zl3073x_pin_props_put(struct zl3073x_pin_props *props)
{ /* Free supported frequency ranges list if it is present */
kfree(props->dpll_props.freq_supported);
/* Put firmware handle if it is present */ if (props->fwnode)
fwnode_handle_put(props->fwnode);
kfree(props);
}
/** * zl3073x_prop_dpll_type_get - get DPLL channel type * @zldev: pointer to zl3073x device * @index: DPLL channel index * * Return: DPLL type for given DPLL channel
*/ enum dpll_type
zl3073x_prop_dpll_type_get(struct zl3073x_dev *zldev, u8 index)
{ constchar *types[ZL3073X_MAX_CHANNELS]; int count;
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.