diff mbox

[RFC,31/37] cbus: retu-rtc: get rid of globals

Message ID 1270656268-7034-32-git-send-email-felipe.balbi@nokia.com (mailing list archive)
State Accepted, archived
Delegated to: Tony Lindgren
Headers show

Commit Message

Felipe Balbi April 7, 2010, 4:04 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/cbus/retu-rtc.c b/drivers/cbus/retu-rtc.c
index 2a1623b..b99c227 100644
--- a/drivers/cbus/retu-rtc.c
+++ b/drivers/cbus/retu-rtc.c
@@ -45,20 +45,27 @@ 
 #include "cbus.h"
 #include "retu.h"
 
-static struct mutex retu_rtc_mutex;
-static u16 retu_rtc_alarm_expired;
-static u16 retu_rtc_reset_occurred;
+struct retu_rtc {
+	struct mutex		mutex;
+	struct completion	sync;
+	struct work_struct	work;
+	struct device		*dev;
+
+	u16			alarm_expired;
+	u16			reset_occurred;
+};
 
-static DECLARE_COMPLETION(retu_rtc_sync);
+#define work_to_rtc(r)	(container_of(r, struct retu_rtc, work))
 
-static void retu_rtc_barrier(void);
+static void retu_rtc_barrier(struct retu_rtc *rtc);
 
 static ssize_t retu_rtc_time_show(struct device *dev, struct device_attribute *attr,
 				  char *buf)
 {
-	u16 dsr, hmr, dsr2;
+	struct retu_rtc		*rtc = dev_get_drvdata(dev);
+	u16			dsr, hmr, dsr2;
 
-	mutex_lock(&retu_rtc_mutex);
+	mutex_lock(&rtc->mutex);
 
 	do {
 		u16 dummy;
@@ -77,7 +84,7 @@  static ssize_t retu_rtc_time_show(struct device *dev, struct device_attribute *a
 		dsr2	= retu_read_reg(RETU_REG_RTCDSR);
 	} while ((dsr != dsr2));
 
-	mutex_unlock(&retu_rtc_mutex);
+	mutex_unlock(&rtc->mutex);
 
 	/*
 	 * Format a 32-bit date-string for userspace
@@ -99,7 +106,9 @@  static ssize_t retu_rtc_time_show(struct device *dev, struct device_attribute *a
 static ssize_t retu_rtc_time_store(struct device *dev, struct device_attribute *attr,
 				   const char *buf, size_t count)
 {
-	mutex_lock(&retu_rtc_mutex);
+	struct retu_rtc		*rtc = dev_get_drvdata(dev);
+
+	mutex_lock(&rtc->mutex);
 	/*
 	 * Writing anything to the day counter forces it to 0
 	 * The seconds counter would be cleared by resetting the minutes counter,
@@ -112,7 +121,7 @@  static ssize_t retu_rtc_time_store(struct device *dev, struct device_attribute *
 	retu_write_reg(RETU_REG_RTCDSR,
 		       retu_read_reg(RETU_REG_RTCDSR) & (1 << 6));
 
-	mutex_unlock(&retu_rtc_mutex);
+	mutex_unlock(&rtc->mutex);
 
 	return count;
 }
@@ -123,6 +132,8 @@  static DEVICE_ATTR(time, S_IRUGO | S_IWUSR, retu_rtc_time_show,
 
 static ssize_t retu_rtc_reset_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
+	struct retu_rtc		*rtc = dev_get_drvdata(dev);
+
 	/*
 	 * Returns the status of the rtc
 	 *
@@ -132,10 +143,10 @@  static ssize_t retu_rtc_reset_show(struct device *dev, struct device_attribute *
 	 * RTC needs to be reset only when both main battery
 	 * _AND_ backup battery are discharged
 	 */
-	return sprintf(buf, "%u\n", retu_rtc_reset_occurred);
+	return sprintf(buf, "%u\n", rtc->reset_occurred);
 }
 
-static void retu_rtc_do_reset(void)
+static void retu_rtc_do_reset(struct retu_rtc *rtc)
 {
 	u16 ccr1;
 
@@ -145,29 +156,30 @@  static void retu_rtc_do_reset(void)
 	/* RTC in normal operating mode */
 	retu_write_reg(RETU_REG_CC1, ccr1 & ~0x0001);
 
-	retu_rtc_barrier();
+	retu_rtc_barrier(rtc);
 	/* Disable alarm and RTC WD */
 	retu_write_reg(RETU_REG_RTCHMAR, 0x7f3f);
 	/* Set Calibration register to default value */
 	retu_write_reg(RETU_REG_RTCCALR, 0x00c0);
 
-	retu_rtc_alarm_expired = 0;
-	retu_rtc_reset_occurred = 1;
+	rtc->alarm_expired = 0;
+	rtc->reset_occurred = 1;
 }
 
 static ssize_t retu_rtc_reset_store(struct device *dev, struct device_attribute *attr,
 				    const char *buf, size_t count)
 {
-	unsigned choice;
+	struct retu_rtc		*rtc = dev_get_drvdata(dev);
+	unsigned		choice;
 
 	if(sscanf(buf, "%u", &choice) != 1)
 		return count;
-	mutex_lock(&retu_rtc_mutex);
+	mutex_lock(&rtc->mutex);
 	if (choice == 0)
-		retu_rtc_reset_occurred = 0;
+		rtc->reset_occurred = 0;
 	else if (choice == 1)
-		retu_rtc_do_reset();
-	mutex_unlock(&retu_rtc_mutex);
+		retu_rtc_do_reset(rtc);
+	mutex_unlock(&rtc->mutex);
 	return count;
 }
 
@@ -177,10 +189,11 @@  static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, retu_rtc_reset_show,
 static ssize_t retu_rtc_alarm_show(struct device *dev, struct device_attribute *attr,
 				   char *buf)
 {
-	u16 chmar;
-	ssize_t retval;
+	struct retu_rtc		*rtc = dev_get_drvdata(dev);
+	ssize_t			retval;
+	u16			chmar;
 
-	mutex_lock(&retu_rtc_mutex);
+	mutex_lock(&rtc->mutex);
 	/*
 	 * Format a 16-bit date-string for userspace
 	 *
@@ -190,7 +203,7 @@  static ssize_t retu_rtc_alarm_show(struct device *dev, struct device_attribute *
 	chmar = retu_read_reg(RETU_REG_RTCHMAR);
 	/* No shifting needed, only masking unrelated bits */
 	retval = sprintf(buf, "0x%04x\n", chmar & 0x1f3f);
-	mutex_unlock(&retu_rtc_mutex);
+	mutex_unlock(&rtc->mutex);
 
 	return retval;
 }
@@ -198,12 +211,15 @@  static ssize_t retu_rtc_alarm_show(struct device *dev, struct device_attribute *
 static ssize_t retu_rtc_alarm_store(struct device *dev, struct device_attribute *attr,
 				    const char *buf, size_t count)
 {
-	u16 chmar;
-	unsigned alrm;
-	unsigned hours;
-	unsigned minutes;
+	struct retu_rtc		*rtc = dev_get_drvdata(dev);
+
+	unsigned		minutes;
+	unsigned		hours;
+	unsigned		alrm;
 
-	mutex_lock(&retu_rtc_mutex);
+	u16			chmar;
+
+	mutex_lock(&rtc->mutex);
 
 	if(sscanf(buf, "%x", &alrm) != 1)
 		return count;
@@ -217,18 +233,18 @@  static ssize_t retu_rtc_alarm_store(struct device *dev, struct device_attribute
 		/* Keeps the RTC watchdog status */
 		chmar = retu_read_reg(RETU_REG_RTCHMAR) & 0x6000;
 		chmar |= alrm & 0x1f3f;	/* Stores the requested alarm */
-		retu_rtc_barrier();
+		retu_rtc_barrier(rtc);
 		retu_write_reg(RETU_REG_RTCHMAR, chmar);
 		/* If the alarm is being disabled */
 		if (hours == 24 && minutes == 60) {
 			/* disable the interrupt */
 			retu_disable_irq(RETU_INT_RTCA);
-			retu_rtc_alarm_expired = 0;
+			rtc->alarm_expired = 0;
 		} else
 			/* enable the interrupt */
 			retu_enable_irq(RETU_INT_RTCA);
 	}
-	mutex_unlock(&retu_rtc_mutex);
+	mutex_unlock(&rtc->mutex);
 
 	return count;
 }
@@ -239,9 +255,10 @@  static DEVICE_ATTR(alarm, S_IRUGO | S_IWUSR, retu_rtc_alarm_show,
 static ssize_t retu_rtc_alarm_expired_show(struct device *dev, struct device_attribute *attr,
 					   char *buf)
 {
-	ssize_t retval;
+	struct retu_rtc		*rtc = dev_get_drvdata(dev);
+	ssize_t			retval;
 
-	retval = sprintf(buf, "%u\n", retu_rtc_alarm_expired);
+	retval = sprintf(buf, "%u\n", rtc->alarm_expired);
 
 	return retval;
 }
@@ -249,7 +266,9 @@  static ssize_t retu_rtc_alarm_expired_show(struct device *dev, struct device_att
 static ssize_t retu_rtc_alarm_expired_store(struct device *dev, struct device_attribute *attr,
 					    const char *buf, size_t count)
 {
-	retu_rtc_alarm_expired = 0;
+	struct retu_rtc		*rtc = dev_get_drvdata(dev);
+
+	rtc->alarm_expired = 0;
 
 	return count;
 }
@@ -261,11 +280,12 @@  static DEVICE_ATTR(alarm_expired, S_IRUGO | S_IWUSR, retu_rtc_alarm_expired_show
 static ssize_t retu_rtc_cal_show(struct device *dev, struct device_attribute *attr,
 				 char *buf)
 {
-	u16 rtccalr1;
+	struct retu_rtc		*rtc = dev_get_drvdata(dev);
+	u16			rtccalr1;
 
-	mutex_lock(&retu_rtc_mutex);
+	mutex_lock(&rtc->mutex);
 	rtccalr1 = retu_read_reg(RETU_REG_RTCCALR);
-	mutex_unlock(&retu_rtc_mutex);
+	mutex_unlock(&rtc->mutex);
 
 	/*
 	 * Shows the status of the Calibration Register.
@@ -281,15 +301,16 @@  static ssize_t retu_rtc_cal_show(struct device *dev, struct device_attribute *at
 static ssize_t retu_rtc_cal_store(struct device *dev, struct device_attribute *attr,
 				  const char *buf, size_t count)
 {
-	unsigned calibration_value;
+	struct retu_rtc		*rtc = dev_get_drvdata(dev);
+	unsigned		calibration_value;
 
 	if (sscanf(buf, "%x", &calibration_value) != 1)
 		return count;
 
-	mutex_lock(&retu_rtc_mutex);
-	retu_rtc_barrier();
+	mutex_lock(&rtc->mutex);
+	retu_rtc_barrier(rtc);
 	retu_write_reg(RETU_REG_RTCCALR, calibration_value & 0x00ff);
-	mutex_unlock(&retu_rtc_mutex);
+	mutex_unlock(&rtc->mutex);
 
 	return count;
 }
@@ -297,45 +318,62 @@  static ssize_t retu_rtc_cal_store(struct device *dev, struct device_attribute *a
 static DEVICE_ATTR(cal, S_IRUGO | S_IWUSR, retu_rtc_cal_show,
 		   retu_rtc_cal_store);
 
-static struct platform_device retu_rtc_device;
+static struct attribute *retu_rtc_attrs[] = {
+	&dev_attr_cal.attr,
+	&dev_attr_alarm_expired.attr,
+	&dev_attr_alarm.attr,
+	&dev_attr_reset.attr,
+	&dev_attr_time.attr,
+	NULL,
+};
+
+static const struct attribute_group retu_rtc_group = {
+	.attrs = retu_rtc_attrs,
+};
 
-static void retu_rtca_disable(void)
+static void retu_rtca_disable(struct retu_rtc *rtc)
 {
 	retu_disable_irq(RETU_INT_RTCA);
-	retu_rtc_alarm_expired = 1;
-	retu_rtc_barrier();
+	rtc->alarm_expired = 1;
+	retu_rtc_barrier(rtc);
 	retu_write_reg(RETU_REG_RTCHMAR, (24 << 8) | 60);
 }
 
-static void retu_rtca_expired(struct work_struct *unused)
+static void retu_rtca_expired(struct work_struct *work)
 {
-	retu_rtca_disable();
-	sysfs_notify(&retu_rtc_device.dev.kobj, NULL, "alarm_expired");
-}
+	struct retu_rtc		*rtc = work_to_rtc(work);
 
-DECLARE_WORK(retu_rtca_work, retu_rtca_expired);
+	retu_rtca_disable(rtc);
+
+	sysfs_notify(&rtc->dev->kobj, NULL, "alarm_expired");
+}
 
 /*
  * RTCHMR RTCHMAR RTCCAL must be accessed within 0.9 s since the seconds
  * interrupt has been signaled in the IDR register
  */
-static void retu_rtcs_interrupt(unsigned long unused)
+static void retu_rtcs_interrupt(unsigned long _rtc)
 {
+	struct retu_rtc		*rtc = (struct retu_rtc *) _rtc;
+
 	retu_ack_irq(RETU_INT_RTCS);
-	complete_all(&retu_rtc_sync);
+	complete_all(&rtc->sync);
 }
 
-static void retu_rtca_interrupt(unsigned long unused)
+static void retu_rtca_interrupt(unsigned long _rtc)
 {
+	struct retu_rtc		*rtc = (struct retu_rtc *) _rtc;
+
 	retu_ack_irq(RETU_INT_RTCA);
-	schedule_work(&retu_rtca_work);
+	schedule_work(&rtc->work);
 }
 
-static int retu_rtc_init_irq(void)
+static int retu_rtc_init_irq(struct retu_rtc *rtc)
 {
 	int ret;
 
-	ret = retu_request_irq(RETU_INT_RTCS, retu_rtcs_interrupt, 0, "RTCS");
+	ret = retu_request_irq(RETU_INT_RTCS, retu_rtcs_interrupt,
+			(unsigned long) rtc, "RTCS");
 	if (ret != 0)
 		return ret;
 	/*
@@ -344,7 +382,8 @@  static int retu_rtc_init_irq(void)
 	 */
 	retu_disable_irq(RETU_INT_RTCS);
 
-	ret = retu_request_irq(RETU_INT_RTCA, retu_rtca_interrupt, 0, "RTCA");
+	ret = retu_request_irq(RETU_INT_RTCA, retu_rtca_interrupt,
+			(unsigned long) rtc, "RTCA");
 	if (ret != 0) {
 		retu_free_irq(RETU_INT_RTCS);
 		return ret;
@@ -357,64 +396,74 @@  static int retu_rtc_init_irq(void)
 
 static int __devinit retu_rtc_probe(struct platform_device *pdev)
 {
-	struct device		*dev = &pdev->dev;
-	int r;
+	struct retu_rtc		*rtc;
+	int			r;
+
+	rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
+	if (!rtc) {
+		dev_err(&pdev->dev, "not enough memory\n");
+		r = -ENOMEM;
+		goto err0;
+	}
 
-	r = retu_get_status();
-	if (!r)
-		return -ENODEV;
+	rtc->dev = &pdev->dev;
+	platform_set_drvdata(pdev, rtc);
+	INIT_WORK(&rtc->work, retu_rtca_expired);
+	mutex_init(&rtc->mutex);
 
-	retu_rtc_alarm_expired = retu_read_reg(RETU_REG_IDR) &
-					       (0x1 << RETU_INT_RTCA);
+	r = retu_get_status();
+	if (!r) {
+		dev_err(&pdev->dev, "retu not initialized\n");
+		goto err1;
+	}
 
-	if ((r = retu_rtc_init_irq()) != 0)
-		return r;
+	rtc->alarm_expired = retu_read_reg(RETU_REG_IDR) &
+		(0x1 << RETU_INT_RTCA);
 
-	mutex_init(&retu_rtc_mutex);
+	r = retu_rtc_init_irq(rtc);
+	if (r < 0) {
+		dev_err(&pdev->dev, "failed to request retu irq\n");
+		goto err1;
+	}
 
 	/* If the calibration register is zero, we've probably lost
 	 * power */
 	if (retu_read_reg(RETU_REG_RTCCALR) & 0x00ff)
-		retu_rtc_reset_occurred = 0;
-	else
-		retu_rtc_do_reset();
-
-	if ((r = device_create_file(dev, &dev_attr_time)) != 0)
-		return r;
-	else if ((r = device_create_file(dev, &dev_attr_reset)) != 0)
-		goto err_unregister_time;
-	else if ((r = device_create_file(dev, &dev_attr_alarm)) != 0)
-		goto err_unregister_reset;
-	else if ((r = device_create_file(dev, &dev_attr_alarm_expired)) != 0)
-		goto err_unregister_alarm;
-	else if ((r = device_create_file(dev, &dev_attr_cal)) != 0)
-		goto err_unregister_alarm_expired;
+		rtc->reset_occurred = 0;
 	else
-		return r;
-
-err_unregister_alarm_expired:
-	device_remove_file(dev, &dev_attr_alarm_expired);
-err_unregister_alarm:
-	device_remove_file(dev, &dev_attr_alarm);
-err_unregister_reset:
-	device_remove_file(dev, &dev_attr_reset);
-err_unregister_time:
-	device_remove_file(dev, &dev_attr_time);
+		retu_rtc_do_reset(rtc);
+
+	r = sysfs_create_group(&pdev->dev.kobj, &retu_rtc_group);
+	if (r) {
+		dev_err(&pdev->dev, "couldn't create sysfs interface\n");
+		goto err2;
+	}
+
+	return 0;
+
+err2:
+	retu_disable_irq(RETU_INT_RTCS);
+	retu_disable_irq(RETU_INT_RTCA);
+	retu_free_irq(RETU_INT_RTCS);
+	retu_free_irq(RETU_INT_RTCA);
+
+err1:
+	kfree(rtc);
+
+err0:
 	return r;
 }
 
 static int __devexit retu_rtc_remove(struct platform_device *pdev)
 {
-	struct device		*dev = &pdev->dev;
+	struct retu_rtc		*rtc = platform_get_drvdata(pdev);
 
 	retu_disable_irq(RETU_INT_RTCS);
+	retu_disable_irq(RETU_INT_RTCA);
 	retu_free_irq(RETU_INT_RTCS);
 	retu_free_irq(RETU_INT_RTCA);
-	device_remove_file(dev, &dev_attr_cal);
-	device_remove_file(dev, &dev_attr_alarm_expired);
-	device_remove_file(dev, &dev_attr_alarm);
-	device_remove_file(dev, &dev_attr_reset);
-	device_remove_file(dev, &dev_attr_time);
+	sysfs_remove_group(&pdev->dev.kobj, &retu_rtc_group);
+	kfree(rtc);
 
 	return 0;
 }
@@ -428,12 +477,12 @@  static struct platform_driver retu_rtc_driver = {
 };
 
 /* This function provides syncronization with the RTCS interrupt handler */
-static void retu_rtc_barrier(void)
+static void retu_rtc_barrier(struct retu_rtc *rtc)
 {
-	INIT_COMPLETION(retu_rtc_sync);
+	INIT_COMPLETION(rtc->sync);
 	retu_ack_irq(RETU_INT_RTCS);
 	retu_enable_irq(RETU_INT_RTCS);
-	wait_for_completion(&retu_rtc_sync);
+	wait_for_completion(&rtc->sync);
 	retu_disable_irq(RETU_INT_RTCS);
 }