drivers/rtc/rtc-m41t80.c

Source file repositories/reference/linux-study-clean/drivers/rtc/rtc-m41t80.c

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-m41t80.c
Extension
.c
Size
27450 bytes
Lines
1045
Domain
Driver Families
Bucket
drivers/rtc
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations wdt_fops = {
	.owner	= THIS_MODULE,
	.read	= wdt_read,
	.unlocked_ioctl = wdt_unlocked_ioctl,
	.compat_ioctl = compat_ptr_ioctl,
	.write	= wdt_write,
	.open	= wdt_open,
	.release = wdt_release,
};

static struct miscdevice wdt_dev = {
	.minor = WATCHDOG_MINOR,
	.name = "watchdog",
	.fops = &wdt_fops,
};

/*
 *	The WDT card needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */
static struct notifier_block wdt_notifier = {
	.notifier_call = wdt_notify_sys,
};
#endif /* CONFIG_RTC_DRV_M41T80_WDT */

/*
 *****************************************************************************
 *
 *	Driver Interface
 *
 *****************************************************************************
 */

static int m41t80_probe(struct i2c_client *client)
{
	struct i2c_adapter *adapter = client->adapter;
	int rc = 0;
	struct rtc_time tm;
	struct m41t80_data *m41t80_data = NULL;
	bool wakeup_source = false;

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
				     I2C_FUNC_SMBUS_BYTE_DATA)) {
		dev_err(&adapter->dev, "doesn't support I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK\n");
		return -ENODEV;
	}

	m41t80_data = devm_kzalloc(&client->dev, sizeof(*m41t80_data),
				   GFP_KERNEL);
	if (!m41t80_data)
		return -ENOMEM;

	m41t80_data->client = client;
	m41t80_data->features = (unsigned long)i2c_get_match_data(client);
	i2c_set_clientdata(client, m41t80_data);

	m41t80_data->rtc =  devm_rtc_allocate_device(&client->dev);
	if (IS_ERR(m41t80_data->rtc))
		return PTR_ERR(m41t80_data->rtc);

	wakeup_source = device_property_read_bool(&client->dev, "wakeup-source");
	if (client->irq > 0) {
		unsigned long irqflags = IRQF_TRIGGER_LOW;

		if (dev_fwnode(&client->dev))
			irqflags = 0;

		rc = devm_request_threaded_irq(&client->dev, client->irq,
					       NULL, m41t80_handle_irq,
					       irqflags | IRQF_ONESHOT,
					       "m41t80", client);
		if (rc) {
			dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
			client->irq = 0;
			wakeup_source = false;
		}
	}
	if (client->irq > 0 || wakeup_source)
		device_init_wakeup(&client->dev, true);
	else
		clear_bit(RTC_FEATURE_ALARM, m41t80_data->rtc->features);

	m41t80_data->rtc->ops = &m41t80_rtc_ops;
	m41t80_data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
	m41t80_data->rtc->range_max = RTC_TIMESTAMP_END_2099;

	if (client->irq <= 0)
		clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, m41t80_data->rtc->features);

	/* Make sure HT (Halt Update) bit is cleared */

Annotation

Implementation Notes