WindCharger: implements hwmon driver for lm95071 device.
Change-Id: I7e4ab00b0d64f07797514555e09fd95cd19d52de
diff --git a/arch/mips/configs/gfwc100_defconfig b/arch/mips/configs/gfwc100_defconfig
old mode 100755
new mode 100644
index 3501c13..3ee0e82
--- a/arch/mips/configs/gfwc100_defconfig
+++ b/arch/mips/configs/gfwc100_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.31
-# Wed Mar 25 14:49:02 2015
+# Thu Apr 9 15:45:38 2015
#
CONFIG_MIPS=y
@@ -367,6 +367,12 @@
# CONFIG_INET_DIAG is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
+# CONFIG_DEFAULT_BIC is not set
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=y
@@ -662,6 +668,8 @@
# CFG80211 needs to be enabled for MAC80211
#
CONFIG_MAC80211_DEFAULT_PS_VALUE=0
+# CONFIG_MAC80211_RC_DEFAULT_PID is not set
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -975,7 +983,24 @@
# CONFIG_PPS is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
-# CONFIG_HWMON is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_IT87 is not set
+CONFIG_SENSORS_LM95071_ATH_MN=y
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
@@ -1020,6 +1045,36 @@
# Special HID drivers
#
# CONFIG_USB_SUPPORT is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_AR9130 is not set
+# CONFIG_USB_GADGET_ATH is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1108,6 +1163,10 @@
# CONFIG_JFFS2_LZMA is not set
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
# CONFIG_CRAMFS is not set
CONFIG_SQUASHFS=y
# CONFIG_SQUASHFS_LZMA is not set
@@ -1119,6 +1178,9 @@
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
+# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
# CONFIG_NILFS2_FS is not set
@@ -1188,6 +1250,9 @@
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_TRACING_SUPPORT=y
# CONFIG_FTRACE is not set
+# CONFIG_BRANCH_PROFILE_NONE is not set
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
# CONFIG_SAMPLES is not set
# CONFIG_HAVE_ARCH_KGDB is not set
CONFIG_CMDLINE="console=ttyS0,115200 root=01:00 rd_start=0x802d0000 rd_size=0x800000 init=/sbin/init mem=32m mtdparts=ath-nor0:256k(u-boot),64k(u-boot-env),6336k(rootfs),1408k(uImage),64k(mib0),64k(ART)"
diff --git a/arch/mips/include/asm/mach-atheros/atheros.h b/arch/mips/include/asm/mach-atheros/atheros.h
index 1eecc44..044be22 100755
--- a/arch/mips/include/asm/mach-atheros/atheros.h
+++ b/arch/mips/include/asm/mach-atheros/atheros.h
@@ -253,39 +253,21 @@
*
*****************************************************************************/
-#define ATH_MN_TEMP_SENSOR_PIN (1 << 14)
-
-/* Enables flash CS. Blocking for mutual exclusion GPIO on pin 14. */
+/*
+ * Enables CS. Blocking for mutual exclusion GPIO 14/5
+ * (depending on the caller).
+ */
static inline void
-ath_mn_spi_enable_flash_cs(void)
+ath_mn_spi_enable_cs(void)
{
ath_spi_down();
ath_spi_enable_soft_access();
- /*
- * Only handles the temp sensor pin, as the flash driver deals with GPIO pin 5
- * on its own.
- */
- ath_gpio_drive_high(ATH_MN_TEMP_SENSOR_PIN);
-}
-
-/* Enables LM sensor CS pin. Blocking for mutual exclusion GPIO on pin 14. */
-static inline void
-ath_mn_spi_enable_lm_cs(void)
-{
- ath_spi_down();
- ath_spi_enable_soft_access();
- /*
- * Only handles the temp sensor pin, as the flash driver deals with GPIO pin 5
- * on its own.
- */
- ath_gpio_drive_low(ATH_MN_TEMP_SENSOR_PIN); /* Enables temp sensor pin. */
}
/* Releases chipselect. */
static inline void
ath_mn_spi_disable_cs(void)
{
- ath_gpio_drive_high(ATH_MN_TEMP_SENSOR_PIN);
ath_spi_disable_soft_access();
ath_spi_up();
}
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 2d50166..2d61d55 100755
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -593,6 +593,17 @@
This driver can also be built as a module. If so, the module
will be called lm93.
+config SENSORS_LM95071_ATH_MN
+ tristate "National Semiconductor LM95071"
+ depends on HWMON && EXPERIMENTAL
+ help
+ If you say yes here you get support for National Semiconductor LM95071
+ sensor chip, as handled for the Atheros GFMN device. This will not work
+ otherwise.
+
+ You have been warned. If you don't know what you're doing, do not select
+ this option.
+
config SENSORS_LTC4215
tristate "Linear Technology LTC4215"
depends on I2C && EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index b793dce..2dbef4c 100755
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -68,6 +68,7 @@
obj-$(CONFIG_SENSORS_LM92) += lm92.o
obj-$(CONFIG_SENSORS_LM93) += lm93.o
obj-$(CONFIG_SENSORS_LM95241) += lm95241.o
+obj-$(CONFIG_SENSORS_LM95071_ATH_MN) += ath_mn_lm95071.o
obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o
obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o
obj-$(CONFIG_SENSORS_MAX1111) += max1111.o
diff --git a/drivers/hwmon/ath_mn_lm95071.c b/drivers/hwmon/ath_mn_lm95071.c
new file mode 100644
index 0000000..8a7d102
--- /dev/null
+++ b/drivers/hwmon/ath_mn_lm95071.c
@@ -0,0 +1,155 @@
+/**
+ * SPI Driver for LM95071 temperature sensor device. This is implemented
+ * specifically in the context of the Atheros 953x GFMN board, and not meant to
+ * be a general solution (a more robust solution would likely be implemented
+ * using a parport interface).
+ *
+ * The LM95071 temperature sensor uses a 3-pin SPI interface. On this board,
+ * the device shares the MISO and CLK pins with the flash device.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/spi/spi.h>
+#include <asm/delay.h>
+#include <atheros.h>
+
+#include "ath_mn_lm95071.h"
+
+#define DRVNAME "lm95071"
+
+struct lm95071 {
+ struct device *dev;
+ void (*lock)(void);
+ void (*unlock)(void);
+};
+
+static void lm_lock(void) {
+ ath_mn_spi_enable_cs();
+ lm_spi_func_clear();
+ ath_gpio_drive_low(ATH_MN_TEMP_SENSOR_PIN);
+ lm_delay();
+}
+
+static void lm_unlock(void) {
+ ath_gpio_drive_high(ATH_MN_TEMP_SENSOR_PIN);
+ lm_spi_func_restore();
+ ath_mn_spi_disable_cs();
+}
+
+static struct lm95071 lm_dev = {
+ .dev = NULL,
+ .lock = lm_lock,
+ .unlock = lm_unlock,
+};
+
+/* Enables continuous conversion mode. */
+static void lm95071_enable_cc(void)
+{
+ lm_dev.lock();
+ lm_spi_delay_16();
+ lm_spi_delay_8();
+ lm_spi_bit_banger(LM_MODE_CC);
+ lm_dev.unlock();
+}
+
+static int lm95071_detect(void)
+{
+ /* TODO(awdavies) Implement this function to read the ID register. */
+ return 0;
+}
+
+static ssize_t lm95071_get_temperature(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s16 temp;
+ u16 raw_temp, sign;
+ int is_negative = 1;
+ lm_dev.lock();
+ lm_spi_delay_16();
+ raw_temp = lm_spi_rd_16();
+ lm_dev.unlock();
+ sign = 0x8000 & raw_temp;
+ if (sign) {
+ raw_temp = ~raw_temp + 1;
+ }
+ temp = raw_temp >> 7;
+
+ /*
+ * LM90571 Temp register has two unused bits at the end. After these are
+ * removed, every number remaining corresponds to 0.03125 C of temperature.
+ *
+ * Official docs here: http://www.ti.com/lit/ds/symlink/lm95071.pdf
+ */
+ return sprintf(buf, "%d\n", sign ? -temp : temp);
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, lm95071_get_temperature, NULL);
+
+static ssize_t lm95071_get_name(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ return sprintf(buf, "%s\n", DRVNAME);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, lm95071_get_name, NULL);
+
+static int lm95071_probe(void)
+{
+ int res;
+ if (lm95071_detect()) {
+ printk(KERN_NOTICE "hwmon_dev_detect failed (lm95071)\n");
+ res = -ENOENT;
+ goto dev_detect_failed;
+ }
+ lm95071_enable_cc();
+ lm_dev.dev = hwmon_device_register(NULL);
+ if (IS_ERR(lm_dev.dev)) {
+ printk(KERN_NOTICE "%x hwmon_dev_reg failed (lm95071)\n", lm_dev.dev);
+ res = PTR_ERR(lm_dev.dev);
+ goto dev_reg_failed;
+ }
+ dev_set_drvdata(lm_dev.dev, &lm_dev);
+ /* Here is where sysfs gets hooked. */
+ if ((res = device_create_file(lm_dev.dev, &dev_attr_temp1_input))
+ || (res = device_create_file(lm_dev.dev, &dev_attr_name))) {
+ printk(KERN_NOTICE "hwmon_dev_create failed (lm95071)\n");
+ goto dev_create_failed;
+ }
+ /* Sanity check. */
+ printk(KERN_NOTICE "lm95071 temp sensor driver initialized.\n");
+ return 0;
+
+dev_create_failed:
+ device_remove_file(lm_dev.dev, &dev_attr_temp1_input);
+ hwmon_device_unregister(lm_dev.dev);
+dev_reg_failed:
+ dev_set_drvdata(lm_dev.dev, NULL);
+dev_detect_failed:
+ return res;
+}
+
+static void lm95071_remove(void)
+{
+ device_remove_file(lm_dev.dev, &dev_attr_temp1_input);
+ device_remove_file(lm_dev.dev, &dev_attr_name);
+ hwmon_device_unregister(lm_dev.dev);
+ dev_set_drvdata(lm_dev.dev, NULL);
+}
+
+static int __init init_lm95071(void)
+{
+ return lm95071_probe();
+}
+
+static void __exit cleanup_lm95071(void)
+{
+ lm95071_remove();
+}
+
+module_init(init_lm95071);
+module_exit(cleanup_lm95071);
diff --git a/drivers/hwmon/ath_mn_lm95071.h b/drivers/hwmon/ath_mn_lm95071.h
new file mode 100644
index 0000000..62108e1
--- /dev/null
+++ b/drivers/hwmon/ath_mn_lm95071.h
@@ -0,0 +1,52 @@
+#ifndef __ATH_MN_LM95071_H__
+#define __ATH_MN_LM95071_H__
+
+#define ATH_MN_TEMP_SENSOR_PIN (1 << 14)
+#define ATH_SPI_CE_LOW 0x60000
+#define ATH_SPI_CE_HIGH 0x60100
+#define ATH_SPI_SC_UDELAY 200
+#define ATH_MUX_SPI_CS_0 0x9 /* SPI_CS_0 signal on QCA mux. */
+
+#define LM_MODE_SD 0xFF /* shutdown mode */
+#define LM_MODE_CC 0x00 /* continuous conversion */
+
+#define lm_delay() udelay(ATH_SPI_SC_UDELAY)
+
+#define lm_be_msb(_val, __i) (((_val) & (1 << (7 - __i))) >> (7 - __i))
+
+#define lm_spi_bit_banger(_byte) do { \
+ int _i; \
+ for (_i = 0; _i < 8; ++_i) { \
+ ath_reg_wr_nf(ATH_SPI_WRITE, ATH_SPI_CE_HIGH | lm_be_msb(_byte, _i)); \
+ lm_delay(); \
+ ath_reg_wr_nf(ATH_SPI_WRITE, ATH_SPI_CE_LOW | lm_be_msb(_byte, _i)); \
+ lm_delay(); \
+ } \
+} while (0)
+
+/*
+ * Clears out signals on GPIO pins 14/5.
+ */
+#define lm_spi_func_clear() do { \
+ ath_reg_rmw_clear(ATH_GPIO_OUT_FUNCTION1, GPIO_OUT_FUNCTION0_ENABLE_GPIO_1_MASK); \
+ ath_reg_rmw_clear(ATH_GPIO_OUT_FUNCTION3, GPIO_OUT_FUNCTION3_ENABLE_GPIO_14_MASK); \
+} while (0)
+
+/* Reenables GPIO pin 5 to functions as CS_0 signal. */
+#define lm_spi_func_restore() do { \
+ ath_reg_rmw_set(ATH_GPIO_OUT_FUNCTION1, \
+ ATH_GPIO_OUT_FUNCTION1_ENABLE_GPIO_5(ATH_MUX_SPI_CS_0)); \
+} while (0)
+
+#define lm_spi_delay_8() lm_spi_bit_banger(0)
+
+#define lm_spi_delay_16() do { \
+ lm_spi_delay_8(); \
+ lm_spi_delay_8(); \
+} while (0);
+
+#define lm_spi_rd_16() (ath_reg_rd(ATH_SPI_RD_STATUS) & 0xFFFF)
+
+#define lm_temp_rd() ((lm_spi_rd_16()) / 4 * 3125)
+
+#endif // __ATH_MN_LM95071_H__
diff --git a/drivers/mtd/devices/ath_flash.c b/drivers/mtd/devices/ath_flash.c
index 5936f1b..8f088b8 100755
--- a/drivers/mtd/devices/ath_flash.c
+++ b/drivers/mtd/devices/ath_flash.c
@@ -104,7 +104,7 @@
if (instr->addr + instr->len > mtd->size)
return (-EINVAL);
- ath_mn_spi_enable_flash_cs();
+ ath_mn_spi_enable_cs();
res = instr->len;
do_div(res, mtd->erasesize);
@@ -147,7 +147,7 @@
return (-EINVAL);
}
- ath_mn_spi_enable_flash_cs();
+ ath_mn_spi_enable_cs();
ath_spi_write_enable();
ath_spi_bit_banger(ATH_SPI_CMD_READ);
@@ -209,7 +209,7 @@
uint32_t addr = 0;
u_char *mem;
- ath_mn_spi_enable_flash_cs();
+ ath_mn_spi_enable_cs();
while (total < len) {
mem = (u_char *) (buf + total);
@@ -488,7 +488,7 @@
uint32_t ori_ear = (uint32_t)ath_spi_rdear();
uint32_t new_ear;
- ath_mn_spi_enable_flash_cs();
+ ath_mn_spi_enable_cs();
while (i < len) {
new_ear = curr_addr >> 24;
ath_spi_wrear(new_ear);
@@ -524,7 +524,7 @@
uint32_t bytes_this_16M, total = 0;
*retlen = len;
- ath_mn_spi_enable_flash_cs();
+ ath_mn_spi_enable_cs();
while (len) {
size_t tmp;
new_ear = curr_addr >> 24;