Current File : //proc/self/root/usr/src/linux-headers-6.8.0-59/include/linux/surface_aggregator/device.h
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Surface System Aggregator Module (SSAM) bus and client-device subsystem.
 *
 * Main interface for the surface-aggregator bus, surface-aggregator client
 * devices, and respective drivers building on top of the SSAM controller.
 * Provides support for non-platform/non-ACPI SSAM clients via dedicated
 * subsystem.
 *
 * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
 */

#ifndef _LINUX_SURFACE_AGGREGATOR_DEVICE_H
#define _LINUX_SURFACE_AGGREGATOR_DEVICE_H

#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
#include <linux/types.h>

#include <linux/surface_aggregator/controller.h>


/* -- Surface System Aggregator Module bus. --------------------------------- */

/**
 * enum ssam_device_domain - SAM device domain.
 * @SSAM_DOMAIN_VIRTUAL:   Virtual device.
 * @SSAM_DOMAIN_SERIALHUB: Physical device connected via Surface Serial Hub.
 */
enum ssam_device_domain {
	SSAM_DOMAIN_VIRTUAL   = 0x00,
	SSAM_DOMAIN_SERIALHUB = 0x01,
};

/**
 * enum ssam_virtual_tc - Target categories for the virtual SAM domain.
 * @SSAM_VIRTUAL_TC_HUB: Device hub category.
 */
enum ssam_virtual_tc {
	SSAM_VIRTUAL_TC_HUB = 0x00,
};

/**
 * struct ssam_device_uid - Unique identifier for SSAM device.
 * @domain:   Domain of the device.
 * @category: Target category of the device.
 * @target:   Target ID of the device.
 * @instance: Instance ID of the device.
 * @function: Sub-function of the device. This field can be used to split a
 *            single SAM device into multiple virtual subdevices to separate
 *            different functionality of that device and allow one driver per
 *            such functionality.
 */
struct ssam_device_uid {
	u8 domain;
	u8 category;
	u8 target;
	u8 instance;
	u8 function;
};

/*
 * Special values for device matching.
 *
 * These values are intended to be used with SSAM_DEVICE(), SSAM_VDEV(), and
 * SSAM_SDEV() exclusively. Specifically, they are used to initialize the
 * match_flags member of the device ID structure. Do not use them directly
 * with struct ssam_device_id or struct ssam_device_uid.
 */
#define SSAM_SSH_TID_ANY	0xffff
#define SSAM_SSH_IID_ANY	0xffff
#define SSAM_SSH_FUN_ANY	0xffff

/**
 * SSAM_DEVICE() - Initialize a &struct ssam_device_id with the given
 * parameters.
 * @d:   Domain of the device.
 * @cat: Target category of the device.
 * @tid: Target ID of the device.
 * @iid: Instance ID of the device.
 * @fun: Sub-function of the device.
 *
 * Initializes a &struct ssam_device_id with the given parameters. See &struct
 * ssam_device_uid for details regarding the parameters. The special values
 * %SSAM_SSH_TID_ANY, %SSAM_SSH_IID_ANY, and %SSAM_SSH_FUN_ANY can be used to specify that
 * matching should ignore target ID, instance ID, and/or sub-function,
 * respectively. This macro initializes the ``match_flags`` field based on the
 * given parameters.
 *
 * Note: The parameters @d and @cat must be valid &u8 values, the parameters
 * @tid, @iid, and @fun must be either valid &u8 values or %SSAM_SSH_TID_ANY,
 * %SSAM_SSH_IID_ANY, or %SSAM_SSH_FUN_ANY, respectively. Other non-&u8 values are not
 * allowed.
 */
#define SSAM_DEVICE(d, cat, tid, iid, fun)					\
	.match_flags = (((tid) != SSAM_SSH_TID_ANY) ? SSAM_MATCH_TARGET : 0)	\
		     | (((iid) != SSAM_SSH_IID_ANY) ? SSAM_MATCH_INSTANCE : 0)	\
		     | (((fun) != SSAM_SSH_FUN_ANY) ? SSAM_MATCH_FUNCTION : 0),	\
	.domain   = d,								\
	.category = cat,							\
	.target   = __builtin_choose_expr((tid) != SSAM_SSH_TID_ANY, (tid), 0),	\
	.instance = __builtin_choose_expr((iid) != SSAM_SSH_IID_ANY, (iid), 0),	\
	.function = __builtin_choose_expr((fun) != SSAM_SSH_FUN_ANY, (fun), 0)

/**
 * SSAM_VDEV() - Initialize a &struct ssam_device_id as virtual device with
 * the given parameters.
 * @cat: Target category of the device.
 * @tid: Target ID of the device.
 * @iid: Instance ID of the device.
 * @fun: Sub-function of the device.
 *
 * Initializes a &struct ssam_device_id with the given parameters in the
 * virtual domain. See &struct ssam_device_uid for details regarding the
 * parameters. The special values %SSAM_SSH_TID_ANY, %SSAM_SSH_IID_ANY, and
 * %SSAM_SSH_FUN_ANY can be used to specify that matching should ignore target ID,
 * instance ID, and/or sub-function, respectively. This macro initializes the
 * ``match_flags`` field based on the given parameters.
 *
 * Note: The parameter @cat must be a valid &u8 value, the parameters @tid,
 * @iid, and @fun must be either valid &u8 values or %SSAM_SSH_TID_ANY,
 * %SSAM_SSH_IID_ANY, or %SSAM_SSH_FUN_ANY, respectively. Other non-&u8 values are not
 * allowed.
 */
#define SSAM_VDEV(cat, tid, iid, fun) \
	SSAM_DEVICE(SSAM_DOMAIN_VIRTUAL, SSAM_VIRTUAL_TC_##cat, SSAM_SSH_TID_##tid, iid, fun)

/**
 * SSAM_SDEV() - Initialize a &struct ssam_device_id as physical SSH device
 * with the given parameters.
 * @cat: Target category of the device.
 * @tid: Target ID of the device.
 * @iid: Instance ID of the device.
 * @fun: Sub-function of the device.
 *
 * Initializes a &struct ssam_device_id with the given parameters in the SSH
 * domain. See &struct ssam_device_uid for details regarding the parameters.
 * The special values %SSAM_SSH_TID_ANY, %SSAM_SSH_IID_ANY, and
 * %SSAM_SSH_FUN_ANY can be used to specify that matching should ignore target
 * ID, instance ID, and/or sub-function, respectively. This macro initializes
 * the ``match_flags`` field based on the given parameters.
 *
 * Note: The parameter @cat must be a valid &u8 value, the parameters @tid,
 * @iid, and @fun must be either valid &u8 values or %SSAM_SSH_TID_ANY,
 * %SSAM_SSH_IID_ANY, or %SSAM_SSH_FUN_ANY, respectively. Other non-&u8 values
 * are not allowed.
 */
#define SSAM_SDEV(cat, tid, iid, fun) \
	SSAM_DEVICE(SSAM_DOMAIN_SERIALHUB, SSAM_SSH_TC_##cat, SSAM_SSH_TID_##tid, iid, fun)

/*
 * enum ssam_device_flags - Flags for SSAM client devices.
 * @SSAM_DEVICE_HOT_REMOVED_BIT:
 *	The device has been hot-removed. Further communication with it may time
 *	out and should be avoided.
 */
enum ssam_device_flags {
	SSAM_DEVICE_HOT_REMOVED_BIT = 0,
};

/**
 * struct ssam_device - SSAM client device.
 * @dev:   Driver model representation of the device.
 * @ctrl:  SSAM controller managing this device.
 * @uid:   UID identifying the device.
 * @flags: Device state flags, see &enum ssam_device_flags.
 */
struct ssam_device {
	struct device dev;
	struct ssam_controller *ctrl;

	struct ssam_device_uid uid;

	unsigned long flags;
};

/**
 * struct ssam_device_driver - SSAM client device driver.
 * @driver:      Base driver model structure.
 * @match_table: Match table specifying which devices the driver should bind to.
 * @probe:       Called when the driver is being bound to a device.
 * @remove:      Called when the driver is being unbound from the device.
 */
struct ssam_device_driver {
	struct device_driver driver;

	const struct ssam_device_id *match_table;

	int  (*probe)(struct ssam_device *sdev);
	void (*remove)(struct ssam_device *sdev);
};

#ifdef CONFIG_SURFACE_AGGREGATOR_BUS

extern const struct device_type ssam_device_type;

/**
 * is_ssam_device() - Check if the given device is a SSAM client device.
 * @d: The device to test the type of.
 *
 * Return: Returns %true if the specified device is of type &struct
 * ssam_device, i.e. the device type points to %ssam_device_type, and %false
 * otherwise.
 */
static inline bool is_ssam_device(struct device *d)
{
	return d->type == &ssam_device_type;
}

#else /* CONFIG_SURFACE_AGGREGATOR_BUS */

static inline bool is_ssam_device(struct device *d)
{
	return false;
}

#endif /* CONFIG_SURFACE_AGGREGATOR_BUS */

/**
 * to_ssam_device() - Casts the given device to a SSAM client device.
 * @d: The device to cast.
 *
 * Casts the given &struct device to a &struct ssam_device. The caller has to
 * ensure that the given device is actually enclosed in a &struct ssam_device,
 * e.g. by calling is_ssam_device().
 *
 * Return: Returns a pointer to the &struct ssam_device wrapping the given
 * device @d.
 */
#define to_ssam_device(d)	container_of_const(d, struct ssam_device, dev)

/**
 * to_ssam_device_driver() - Casts the given device driver to a SSAM client
 * device driver.
 * @d: The driver to cast.
 *
 * Casts the given &struct device_driver to a &struct ssam_device_driver. The
 * caller has to ensure that the given driver is actually enclosed in a
 * &struct ssam_device_driver.
 *
 * Return: Returns the pointer to the &struct ssam_device_driver wrapping the
 * given device driver @d.
 */
#define to_ssam_device_driver(d)	container_of_const(d, struct ssam_device_driver, driver)

const struct ssam_device_id *ssam_device_id_match(const struct ssam_device_id *table,
						  const struct ssam_device_uid uid);

const struct ssam_device_id *ssam_device_get_match(const struct ssam_device *dev);

const void *ssam_device_get_match_data(const struct ssam_device *dev);

struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl,
				      struct ssam_device_uid uid);

int ssam_device_add(struct ssam_device *sdev);
void ssam_device_remove(struct ssam_device *sdev);

/**
 * ssam_device_mark_hot_removed() - Mark the given device as hot-removed.
 * @sdev: The device to mark as hot-removed.
 *
 * Mark the device as having been hot-removed. This signals drivers using the
 * device that communication with the device should be avoided and may lead to
 * timeouts.
 */
static inline void ssam_device_mark_hot_removed(struct ssam_device *sdev)
{
	dev_dbg(&sdev->dev, "marking device as hot-removed\n");
	set_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
}

/**
 * ssam_device_is_hot_removed() - Check if the given device has been
 * hot-removed.
 * @sdev: The device to check.
 *
 * Checks if the given device has been marked as hot-removed. See
 * ssam_device_mark_hot_removed() for more details.
 *
 * Return: Returns ``true`` if the device has been marked as hot-removed.
 */
static inline bool ssam_device_is_hot_removed(struct ssam_device *sdev)
{
	return test_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
}

/**
 * ssam_device_get() - Increment reference count of SSAM client device.
 * @sdev: The device to increment the reference count of.
 *
 * Increments the reference count of the given SSAM client device by
 * incrementing the reference count of the enclosed &struct device via
 * get_device().
 *
 * See ssam_device_put() for the counter-part of this function.
 *
 * Return: Returns the device provided as input.
 */
static inline struct ssam_device *ssam_device_get(struct ssam_device *sdev)
{
	return sdev ? to_ssam_device(get_device(&sdev->dev)) : NULL;
}

/**
 * ssam_device_put() - Decrement reference count of SSAM client device.
 * @sdev: The device to decrement the reference count of.
 *
 * Decrements the reference count of the given SSAM client device by
 * decrementing the reference count of the enclosed &struct device via
 * put_device().
 *
 * See ssam_device_get() for the counter-part of this function.
 */
static inline void ssam_device_put(struct ssam_device *sdev)
{
	if (sdev)
		put_device(&sdev->dev);
}

/**
 * ssam_device_get_drvdata() - Get driver-data of SSAM client device.
 * @sdev: The device to get the driver-data from.
 *
 * Return: Returns the driver-data of the given device, previously set via
 * ssam_device_set_drvdata().
 */
static inline void *ssam_device_get_drvdata(struct ssam_device *sdev)
{
	return dev_get_drvdata(&sdev->dev);
}

/**
 * ssam_device_set_drvdata() - Set driver-data of SSAM client device.
 * @sdev: The device to set the driver-data of.
 * @data: The data to set the device's driver-data pointer to.
 */
static inline void ssam_device_set_drvdata(struct ssam_device *sdev, void *data)
{
	dev_set_drvdata(&sdev->dev, data);
}

int __ssam_device_driver_register(struct ssam_device_driver *d, struct module *o);
void ssam_device_driver_unregister(struct ssam_device_driver *d);

/**
 * ssam_device_driver_register() - Register a SSAM client device driver.
 * @drv: The driver to register.
 */
#define ssam_device_driver_register(drv) \
	__ssam_device_driver_register(drv, THIS_MODULE)

/**
 * module_ssam_device_driver() - Helper macro for SSAM device driver
 * registration.
 * @drv: The driver managed by this module.
 *
 * Helper macro to register a SSAM device driver via module_init() and
 * module_exit(). This macro may only be used once per module and replaces the
 * aforementioned definitions.
 */
#define module_ssam_device_driver(drv)			\
	module_driver(drv, ssam_device_driver_register,	\
		      ssam_device_driver_unregister)


/* -- Helpers for controller and hub devices. ------------------------------- */

#ifdef CONFIG_SURFACE_AGGREGATOR_BUS

int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
			    struct fwnode_handle *node);
void ssam_remove_clients(struct device *dev);

#else /* CONFIG_SURFACE_AGGREGATOR_BUS */

static inline int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
					  struct fwnode_handle *node)
{
	return 0;
}

static inline void ssam_remove_clients(struct device *dev) {}

#endif /* CONFIG_SURFACE_AGGREGATOR_BUS */

/**
 * ssam_register_clients() - Register all client devices defined under the
 * given parent device.
 * @dev: The parent device under which clients should be registered.
 * @ctrl: The controller with which client should be registered.
 *
 * Register all clients that have via firmware nodes been defined as children
 * of the given (parent) device. The respective child firmware nodes will be
 * associated with the correspondingly created child devices.
 *
 * The given controller will be used to instantiate the new devices. See
 * ssam_device_add() for details.
 *
 * Return: Returns zero on success, nonzero on failure.
 */
static inline int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl)
{
	return __ssam_register_clients(dev, ctrl, dev_fwnode(dev));
}

/**
 * ssam_device_register_clients() - Register all client devices defined under
 * the given SSAM parent device.
 * @sdev: The parent device under which clients should be registered.
 *
 * Register all clients that have via firmware nodes been defined as children
 * of the given (parent) device. The respective child firmware nodes will be
 * associated with the correspondingly created child devices.
 *
 * The controller used by the parent device will be used to instantiate the new
 * devices. See ssam_device_add() for details.
 *
 * Return: Returns zero on success, nonzero on failure.
 */
static inline int ssam_device_register_clients(struct ssam_device *sdev)
{
	return ssam_register_clients(&sdev->dev, sdev->ctrl);
}


/* -- Helpers for client-device requests. ----------------------------------- */

/**
 * SSAM_DEFINE_SYNC_REQUEST_CL_N() - Define synchronous client-device SAM
 * request function with neither argument nor return value.
 * @name: Name of the generated function.
 * @spec: Specification (&struct ssam_request_spec_md) defining the request.
 *
 * Defines a function executing the synchronous SAM request specified by
 * @spec, with the request having neither argument nor return value. Device
 * specifying parameters are not hard-coded, but instead are provided via the
 * client device, specifically its UID, supplied when calling this function.
 * The generated function takes care of setting up the request struct, buffer
 * allocation, as well as execution of the request itself, returning once the
 * request has been fully completed. The required transport buffer will be
 * allocated on the stack.
 *
 * The generated function is defined as ``static int name(struct ssam_device
 * *sdev)``, returning the status of the request, which is zero on success and
 * negative on failure. The ``sdev`` parameter specifies both the target
 * device of the request and by association the controller via which the
 * request is sent.
 *
 * Refer to ssam_request_do_sync_onstack() for more details on the behavior of
 * the generated function.
 */
#define SSAM_DEFINE_SYNC_REQUEST_CL_N(name, spec...)			\
	SSAM_DEFINE_SYNC_REQUEST_MD_N(__raw_##name, spec)		\
	static int name(struct ssam_device *sdev)			\
	{								\
		return __raw_##name(sdev->ctrl, sdev->uid.target,	\
				    sdev->uid.instance);		\
	}

/**
 * SSAM_DEFINE_SYNC_REQUEST_CL_W() - Define synchronous client-device SAM
 * request function with argument.
 * @name:  Name of the generated function.
 * @atype: Type of the request's argument.
 * @spec:  Specification (&struct ssam_request_spec_md) defining the request.
 *
 * Defines a function executing the synchronous SAM request specified by
 * @spec, with the request taking an argument of type @atype and having no
 * return value. Device specifying parameters are not hard-coded, but instead
 * are provided via the client device, specifically its UID, supplied when
 * calling this function. The generated function takes care of setting up the
 * request struct, buffer allocation, as well as execution of the request
 * itself, returning once the request has been fully completed. The required
 * transport buffer will be allocated on the stack.
 *
 * The generated function is defined as ``static int name(struct ssam_device
 * *sdev, const atype *arg)``, returning the status of the request, which is
 * zero on success and negative on failure. The ``sdev`` parameter specifies
 * both the target device of the request and by association the controller via
 * which the request is sent. The request's argument is specified via the
 * ``arg`` pointer.
 *
 * Refer to ssam_request_do_sync_onstack() for more details on the behavior of
 * the generated function.
 */
#define SSAM_DEFINE_SYNC_REQUEST_CL_W(name, atype, spec...)		\
	SSAM_DEFINE_SYNC_REQUEST_MD_W(__raw_##name, atype, spec)	\
	static int name(struct ssam_device *sdev, const atype *arg)	\
	{								\
		return __raw_##name(sdev->ctrl, sdev->uid.target,	\
				    sdev->uid.instance, arg);		\
	}

/**
 * SSAM_DEFINE_SYNC_REQUEST_CL_R() - Define synchronous client-device SAM
 * request function with return value.
 * @name:  Name of the generated function.
 * @rtype: Type of the request's return value.
 * @spec:  Specification (&struct ssam_request_spec_md) defining the request.
 *
 * Defines a function executing the synchronous SAM request specified by
 * @spec, with the request taking no argument but having a return value of
 * type @rtype. Device specifying parameters are not hard-coded, but instead
 * are provided via the client device, specifically its UID, supplied when
 * calling this function. The generated function takes care of setting up the
 * request struct, buffer allocation, as well as execution of the request
 * itself, returning once the request has been fully completed. The required
 * transport buffer will be allocated on the stack.
 *
 * The generated function is defined as ``static int name(struct ssam_device
 * *sdev, rtype *ret)``, returning the status of the request, which is zero on
 * success and negative on failure. The ``sdev`` parameter specifies both the
 * target device of the request and by association the controller via which
 * the request is sent. The request's return value is written to the memory
 * pointed to by the ``ret`` parameter.
 *
 * Refer to ssam_request_do_sync_onstack() for more details on the behavior of
 * the generated function.
 */
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...)		\
	SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec)	\
	static int name(struct ssam_device *sdev, rtype *ret)		\
	{								\
		return __raw_##name(sdev->ctrl, sdev->uid.target,	\
				    sdev->uid.instance, ret);		\
	}

/**
 * SSAM_DEFINE_SYNC_REQUEST_CL_WR() - Define synchronous client-device SAM
 * request function with argument and return value.
 * @name:  Name of the generated function.
 * @atype: Type of the request's argument.
 * @rtype: Type of the request's return value.
 * @spec:  Specification (&struct ssam_request_spec_md) defining the request.
 *
 * Defines a function executing the synchronous SAM request specified by @spec,
 * with the request taking an argument of type @atype and having a return value
 * of type @rtype. Device specifying parameters are not hard-coded, but instead
 * are provided via the client device, specifically its UID, supplied when
 * calling this function. The generated function takes care of setting up the
 * request struct, buffer allocation, as well as execution of the request
 * itself, returning once the request has been fully completed. The required
 * transport buffer will be allocated on the stack.
 *
 * The generated function is defined as ``static int name(struct ssam_device
 * *sdev, const atype *arg, rtype *ret)``, returning the status of the request,
 * which is zero on success and negative on failure. The ``sdev`` parameter
 * specifies both the target device of the request and by association the
 * controller via which the request is sent. The request's argument is
 * specified via the ``arg`` pointer. The request's return value is written to
 * the memory pointed to by the ``ret`` parameter.
 *
 * Refer to ssam_request_do_sync_onstack() for more details on the behavior of
 * the generated function.
 */
#define SSAM_DEFINE_SYNC_REQUEST_CL_WR(name, atype, rtype, spec...)		\
	SSAM_DEFINE_SYNC_REQUEST_MD_WR(__raw_##name, atype, rtype, spec)	\
	static int name(struct ssam_device *sdev, const atype *arg, rtype *ret)	\
	{									\
		return __raw_##name(sdev->ctrl, sdev->uid.target,		\
				    sdev->uid.instance, arg, ret);		\
	}


/* -- Helpers for client-device notifiers. ---------------------------------- */

/**
 * ssam_device_notifier_register() - Register an event notifier for the
 * specified client device.
 * @sdev: The device the notifier should be registered on.
 * @n:    The event notifier to register.
 *
 * Register an event notifier. Increment the usage counter of the associated
 * SAM event if the notifier is not marked as an observer. If the event is not
 * marked as an observer and is currently not enabled, it will be enabled
 * during this call. If the notifier is marked as an observer, no attempt will
 * be made at enabling any event and no reference count will be modified.
 *
 * Notifiers marked as observers do not need to be associated with one specific
 * event, i.e. as long as no event matching is performed, only the event target
 * category needs to be set.
 *
 * Return: Returns zero on success, %-ENOSPC if there have already been
 * %INT_MAX notifiers for the event ID/type associated with the notifier block
 * registered, %-ENOMEM if the corresponding event entry could not be
 * allocated, %-ENODEV if the device is marked as hot-removed. If this is the
 * first time that a notifier block is registered for the specific associated
 * event, returns the status of the event-enable EC-command.
 */
static inline int ssam_device_notifier_register(struct ssam_device *sdev,
						struct ssam_event_notifier *n)
{
	/*
	 * Note that this check does not provide any guarantees whatsoever as
	 * hot-removal could happen at any point and we can't protect against
	 * it. Nevertheless, if we can detect hot-removal, bail early to avoid
	 * communication timeouts.
	 */
	if (ssam_device_is_hot_removed(sdev))
		return -ENODEV;

	return ssam_notifier_register(sdev->ctrl, n);
}

/**
 * ssam_device_notifier_unregister() - Unregister an event notifier for the
 * specified client device.
 * @sdev: The device the notifier has been registered on.
 * @n:    The event notifier to unregister.
 *
 * Unregister an event notifier. Decrement the usage counter of the associated
 * SAM event if the notifier is not marked as an observer. If the usage counter
 * reaches zero, the event will be disabled.
 *
 * In case the device has been marked as hot-removed, the event will not be
 * disabled on the EC, as in those cases any attempt at doing so may time out.
 *
 * Return: Returns zero on success, %-ENOENT if the given notifier block has
 * not been registered on the controller. If the given notifier block was the
 * last one associated with its specific event, returns the status of the
 * event-disable EC-command.
 */
static inline int ssam_device_notifier_unregister(struct ssam_device *sdev,
						  struct ssam_event_notifier *n)
{
	return __ssam_notifier_unregister(sdev->ctrl, n,
					  !ssam_device_is_hot_removed(sdev));
}

#endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */
¿Qué es la limpieza dental de perros? - Clínica veterinaria


Es la eliminación del sarro y la placa adherida a la superficie de los dientes mediante un equipo de ultrasonidos que garantiza la integridad de las piezas dentales a la vez que elimina en profundidad cualquier resto de suciedad.

A continuación se procede al pulido de los dientes mediante una fresa especial que elimina la placa bacteriana y devuelve a los dientes el aspecto sano que deben tener.

Una vez terminado todo el proceso, se mantiene al perro en observación hasta que se despierta de la anestesia, bajo la atenta supervisión de un veterinario.

¿Cada cuánto tiempo tengo que hacerle una limpieza dental a mi perro?

A partir de cierta edad, los perros pueden necesitar una limpieza dental anual o bianual. Depende de cada caso. En líneas generales, puede decirse que los perros de razas pequeñas suelen acumular más sarro y suelen necesitar una atención mayor en cuanto a higiene dental.


Riesgos de una mala higiene


Los riesgos más evidentes de una mala higiene dental en los perros son los siguientes:

  • Cuando la acumulación de sarro no se trata, se puede producir una inflamación y retracción de las encías que puede descalzar el diente y provocar caídas.
  • Mal aliento (halitosis).
  • Sarro perros
  • Puede ir a más
  • Las bacterias de la placa pueden trasladarse a través del torrente circulatorio a órganos vitales como el corazón ocasionando problemas de endocarditis en las válvulas. Las bacterias pueden incluso acantonarse en huesos (La osteomielitis es la infección ósea, tanto cortical como medular) provocando mucho dolor y una artritis séptica).

¿Cómo se forma el sarro?

El sarro es la calcificación de la placa dental. Los restos de alimentos, junto con las bacterias presentes en la boca, van a formar la placa bacteriana o placa dental. Si la placa no se retira, al mezclarse con la saliva y los minerales presentes en ella, reaccionará formando una costra. La placa se calcifica y se forma el sarro.

El sarro, cuando se forma, es de color blanquecino pero a medida que pasa el tiempo se va poniendo amarillo y luego marrón.

Síntomas de una pobre higiene dental
La señal más obvia de una mala salud dental canina es el mal aliento.

Sin embargo, a veces no es tan fácil de detectar
Y hay perros que no se dejan abrir la boca por su dueño. Por ejemplo…

Recientemente nos trajeron a la clínica a un perro que parpadeaba de un ojo y decía su dueño que le picaba un lado de la cara. Tenía molestias y dificultad para comer, lo que había llevado a sus dueños a comprarle comida blanda (que suele ser un poco más cara y llevar más contenido en grasa) durante medio año. Después de una exploración oftalmológica, nos dimos cuenta de que el ojo tenía una úlcera en la córnea probablemente de rascarse . Además, el canto lateral del ojo estaba inflamado. Tenía lo que en humanos llamamos flemón pero como era un perro de pelo largo, no se le notaba a simple vista. Al abrirle la boca nos llamó la atención el ver una muela llena de sarro. Le realizamos una radiografía y encontramos una fístula que llegaba hasta la parte inferior del ojo.

Le tuvimos que extraer la muela. Tras esto, el ojo se curó completamente con unos colirios y una lentilla protectora de úlcera. Afortunadamente, la úlcera no profundizó y no perforó el ojo. Ahora el perro come perfectamente a pesar de haber perdido una muela.

¿Cómo mantener la higiene dental de tu perro?
Hay varias maneras de prevenir problemas derivados de la salud dental de tu perro.

Limpiezas de dientes en casa
Es recomendable limpiar los dientes de tu perro semanal o diariamente si se puede. Existe una gran variedad de productos que se pueden utilizar:

Pastas de dientes.
Cepillos de dientes o dedales para el dedo índice, que hacen más fácil la limpieza.
Colutorios para echar en agua de bebida o directamente sobre el diente en líquido o en spray.

En la Clínica Tus Veterinarios enseñamos a nuestros clientes a tomar el hábito de limpiar los dientes de sus perros desde que son cachorros. Esto responde a nuestro compromiso con la prevención de enfermedades caninas.

Hoy en día tenemos muchos clientes que limpian los dientes todos los días a su mascota, y como resultado, se ahorran el dinero de hacer limpiezas dentales profesionales y consiguen una mejor salud de su perro.


Limpiezas dentales profesionales de perros y gatos

Recomendamos hacer una limpieza dental especializada anualmente. La realizamos con un aparato de ultrasonidos que utiliza agua para quitar el sarro. Después, procedemos a pulir los dientes con un cepillo de alta velocidad y una pasta especial. Hacemos esto para proteger el esmalte.

La frecuencia de limpiezas dentales necesaria varía mucho entre razas. En general, las razas grandes tienen buena calidad de esmalte, por lo que no necesitan hacerlo tan a menudo e incluso pueden pasarse la vida sin requerir una limpieza. Sin embargo, razas pequeñas como el Yorkshire o el Maltés, deben hacérselas todos los años desde cachorros si se quiere conservar sus piezas dentales.

Otro factor fundamental es la calidad del pienso. Algunas marcas han diseñado croquetas que limpian la superficie del diente y de la muela al masticarse.

Ultrasonido para perros

¿Se necesita anestesia para las limpiezas dentales de perros y gatos?

La limpieza dental en perros no es una técnica que pueda practicarse sin anestesia general , aunque hay veces que los propietarios no quieren anestesiar y si tiene poco sarro y el perro es muy bueno se puede intentar…… , pero no se va a poder pulir ni acceder a todas la zona de la boca …. Además los limpiadores dentales van a irrigar agua y hay riesgo de aspiración a vías respiratorias si no se realiza una anestesia correcta con intubación traqueal . En resumen , sin anestesia no se va hacer una correcta limpieza dental.

Tampoco sirve la sedación ya que necesitamos que el animal esté totalmente quieto, y el veterinario tenga un acceso completo a todas sus piezas dentales y encías.

Alimentos para la limpieza dental

Hay que tener cierto cuidado a la hora de comprar determinados alimentos porque no todos son saludables. Algunos tienen demasiado contenido graso, que en exceso puede causar problemas cardiovasculares y obesidad.

Los mejores alimentos para los dientes son aquellos que están elaborados por empresas farmacéuticas y llevan componentes químicos con tratamientos específicos para el diente del perro. Esto implica no solo limpieza a través de la acción mecánica de morder sino también un tratamiento antibacteriano para prevenir el sarro.

Conclusión

Si eres como la mayoría de dueños, por falta de tiempo , es probable que no estés prestando la suficiente atención a la limpieza dental de tu perro. Por eso te animamos a que comiences a limpiar los dientes de tu perro y consideres atender a su higiene bucal con frecuencia.

Estas simples medidas pueden conllevar a que tu perro tenga una vida más larga y mucho más saludable.

Si te resulta imposible introducir un cepillo de dientes a tu perro en la boca, pásate con él por clínica Tus Veterinarios y te explicamos cómo hacerlo.

Necesitas hacer una limpieza dental profesional a tu mascota?
Llámanos al 622575274 o contacta con nosotros

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

¡Hola!