/** * struct viortc_class - RTC class wrapper * @viortc: virtio_rtc device data * @rtc: RTC device * @vio_clk_id: virtio_rtc clock id * @stopped: Whether RTC ops are disallowed. Access protected by rtc_lock().
*/ struct viortc_class { struct viortc_dev *viortc; struct rtc_device *rtc;
u16 vio_clk_id; bool stopped;
};
/** * viortc_class_get_locked() - get RTC class wrapper, if ops allowed * @dev: virtio device * * Gets the RTC class wrapper from the virtio device, if it is available and * ops are allowed. * * Context: Caller must hold rtc_lock(). * Return: RTC class wrapper if available and ops allowed, ERR_PTR otherwise.
*/ staticstruct viortc_class *viortc_class_get_locked(struct device *dev)
{ struct viortc_class *viortc_class;
viortc_class = viortc_class_from_dev(dev); if (IS_ERR(viortc_class)) return viortc_class;
if (viortc_class->stopped) return ERR_PTR(-EBUSY);
return viortc_class;
}
/** * viortc_class_read_time() - RTC class op read_time * @dev: virtio device * @tm: read time * * Context: Process context. * Return: Zero on success, negative error code otherwise.
*/ staticint viortc_class_read_time(struct device *dev, struct rtc_time *tm)
{ struct viortc_class *viortc_class;
time64_t sec; int ret;
u64 ns;
viortc_class = viortc_class_get_locked(dev); if (IS_ERR(viortc_class)) return PTR_ERR(viortc_class);
ret = viortc_read(viortc_class->viortc, viortc_class->vio_clk_id, &ns); if (ret) return ret;
sec = div_u64(ns, NSEC_PER_SEC);
rtc_time64_to_tm(sec, tm);
return 0;
}
/** * viortc_class_read_alarm() - RTC class op read_alarm * @dev: virtio device * @alrm: alarm read out * * Context: Process context. * Return: Zero on success, negative error code otherwise.
*/ staticint viortc_class_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ struct viortc_class *viortc_class;
time64_t alarm_time_sec;
u64 alarm_time_ns; bool enabled; int ret;
viortc_class = viortc_class_get_locked(dev); if (IS_ERR(viortc_class)) return PTR_ERR(viortc_class);
ret = viortc_read_alarm(viortc_class->viortc, viortc_class->vio_clk_id,
&alarm_time_ns, &enabled); if (ret) return ret;
/** * viortc_class_stop() - disallow RTC class ops * @viortc_class: RTC class wrapper * * Context: Process context. Caller must NOT hold rtc_lock().
*/ void viortc_class_stop(struct viortc_class *viortc_class)
{
rtc_lock(viortc_class->rtc);
viortc_class->stopped = true;
rtc_unlock(viortc_class->rtc);
}
/** * viortc_class_register() - register RTC class device * @viortc_class: RTC class wrapper * * Context: Process context. * Return: Zero on success, negative error code otherwise.
*/ int viortc_class_register(struct viortc_class *viortc_class)
{ return devm_rtc_register_device(viortc_class->rtc);
}
/** * viortc_class_init() - init RTC class wrapper and device * @viortc: device data * @vio_clk_id: virtio_rtc clock id * @have_alarm: have alarm feature * @parent_dev: virtio device * * Context: Process context. * Return: RTC class wrapper on success, ERR_PTR otherwise.
*/ struct viortc_class *viortc_class_init(struct viortc_dev *viortc,
u16 vio_clk_id, bool have_alarm, struct device *parent_dev)
{ struct viortc_class *viortc_class; struct rtc_device *rtc;
viortc_class =
devm_kzalloc(parent_dev, sizeof(*viortc_class), GFP_KERNEL); if (!viortc_class) return ERR_PTR(-ENOMEM);
rtc = devm_rtc_allocate_device(parent_dev); if (IS_ERR(rtc)) return ERR_CAST(rtc);
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.